使用行ID指定直接行访问
对于某些应用程序,您可以使用 ROWID 列的值直接导航到某一行。
准备工作
确保查询符合直接行访问的条件。 要符合条件,搜索条件必须是一个布尔值,第一阶段谓词符合以下标准之一:
- 一个简单的布尔术语谓词,形式如下:
非列表达式包含RID函数的结果。RID (table designator) = noncolumn expression - 一个布尔复合术语,使用“与”运算符将多个简单谓词组合在一起,其中一个简单谓词符合第一个条件。
关于本任务
入门概念
ROWID列用于唯一标识表格中的每一行。 使用ROWID列,您可以编写查询语句,直接跳转到表格中的某一行,因为该列隐含地包含了该行的位置。 您可以将 ROWID 列定义为默认生成或始终生成:
- 如果将列定义为默认生成,则可以插入一个值。 Db2 如果您没有提供默认值,则系统会提供默认值。 但是,为了能够插入一个明确的值(通过使用带有VALUES子句的INSERT语句),您必须在该列上创建一个唯一的索引。
- 如果将列定义为“始终生成”(默认设置),则 Db2 始终为该列生成一个唯一的值。 您不能在该列中插入数据。 在这种情况下, Db2 不需要索引来保证唯一值。
当您选择ROWID列时,该值隐含了所检索行的位置。 如果您在后续查询的搜索条件中使用 ROWID 列中的值, Db2 可以选择直接导航到该行。
如果您将表中的列定义为 ROWID 数据类型,则只有在将列定义为 GENERATED ALWAYS 时, Db2 才会为表中的每一行提供一个唯一的值。 ROWID列中值的目的是唯一标识表中的行。
您可以使用ROWID列编写直接跳转到某行的查询,这在需要高性能的情况下非常有用。 这种无需使用索引或扫描表空间的直接导航称为直接行访问。 此外,包含LOB列的表必须包含ROWID列。 本主题讨论了在直接行访问中使用ROWID列。
例如,假设雇员表定义如下:
CREATE TABLE EMPLOYEE
(EMP_ROWID ROWID NOT NULL GENERATED ALWAYS,
EMPNO SMALLINT,
NAME CHAR(30),
SALARY DECIMAL(7,2),
WORKDEPT SMALLINT);以下代码使用INSERT语句中的SELECT来从插入到EMPLOYEE表的新行中获取ROWID列的值。 然后使用该值来更新工资列。EXEC SQL BEGIN DECLARE SECTION;
SQL TYPE IS ROWID hv_emp_rowid;
short hv_dept, hv_empno;
char hv_name[30];
decimal(7,2) hv_salary;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL
SELECT EMP_ROWID INTO :hv_emp_rowid
FROM FINAL TABLE (INSERT INTO EMPLOYEE
VALUES (DEFAULT, :hv_empno, :hv_name, :hv_salary, :hv_dept));
EXEC SQL
UPDATE EMPLOYEE
SET SALARY = SALARY + 1200
WHERE EMP_ROWID = :hv_emp_rowid;
EXEC SQL COMMIT;为了使 Db2 能够使用直接行访问进行更新操作,SELECT from INSERT语句和UPDATE语句必须在同一工作单元内执行。 或者,您可以使用MERGE语句中的SELECT。 MERGE语句将INSERT和UPDATE操作作为一条协调语句执行。
要求 :要使用直接行访问,必须在提交前使用检索到的 ROWID 值。 当您的应用程序提交时,它就会释放对表空间的要求。 提交后,如果您的表空间运行了REORG,则行的物理位置可能会发生变化。
限制 :通常情况下,您不能将 ROWID 列用作跨多个表的单个列值。 由于表空间的REORG,表中特定行的ROWID值可能会随时间变化。 特别是,不能将 ROWID 列用作父键或外键的一部分。
从ROWID列中检索到的值是一个长度可变的字符值,它不是单调递增或递减的(该值并不总是增加或减少)。 因此,ROWID列无法为订单号或员工编号等多种实体键提供合适的值。
过程
使用 ROWID 值指定直接行访问:
在SELECT、DELETE或UPDATE语句的搜索条件中调用RID内置函数。
RID 函数用于返回行的 RID,您可以使用它来唯一标识行。
限制 :由于在运行REORG实用程序时, Db2 可能会重复使用RID编号,因此当对同一行多次调用RID函数时,可能会返回不同的值。
如果您指定了 RID,而 Db2 无法通过直接行访问找到该行,则 Db2 不会切换到其他访问方法。 相反, Db2 没有返回任何行。