伪列(Pseudocolumn)的行为与表中的列相同,但并未存储具体数值。因此,伪列只具备读属性,您不可以对伪列进行插入、更新、删除的等行为。

注意

OceanBase 不支持 ROWID 伪列。

层次查询伪列

层次查询伪列仅在层次查询中有效,要在查询中定义层次结构关系,必须使用 CONNECT BY 子句。层次查询伪列有:

  • CONNECT_BY_ISCYCLE 伪列
  • CONNECT_BY_ISLEAF 伪列
  • LEVEL 伪列

CONNECT_BY_ISCYCLE 伪列

CONNECT_BY_ISCYCLE 伪列用来协助标记循环是从哪一行开始的。如当前行的子节点同时也是其祖先节点之一,则CONNECT_BY_ISCYCLE 返回 1,否则返回 0。

CONNECT_BY_ISCYCLE 需要配合 CONNECT BY 子句的 NOCYCLE 使用,否则查询结果会因树状结果存在循环而报错。

CONNECT_BY_ISLEAF 伪列

CONNECT_BY_ISLEAF 伪列用来协助标记层次结构的叶子节点。如当前行无子节点即为树的叶子节点时,返回 1,否则返回 0。

LEVEL 伪列

LEVEL 伪列用来协助标记节点的层次。层次结构中,根为第 1 层,根的子结点为第 2 层,之后以此类推。例如,根节点的 LEVEL 值会返回 1,根节点的子节点的 LEVEL 值会返回 2,之后以此类推。

序列伪列

序列(Sequence)伪列是数据库按照一定规则生成的自增数字序列。因其自增的特性,通常被用作主键和唯一键。序列伪列有两种取值方法:

  • CURRVAL:返回序列的当前值。
  • NEXTVAL:返回序列的下一个自增值。

使用序列伪列时,必须在 CURRVALNEXTVAL 前带上序列的名称,并用句点(.)引用。例如,序列的名称为 SEQ_FOO,则可以通过 SEQ_FOO.CURRVAL 获取 SEQ_FOO 序列的当前值。同样,可以通过 SEQ_FOO.NEXTVAL 获取 SEQ_FOO 序列的下一个自增值。

序列伪列的应用场景

序列伪列 CURRVALNEXTVAL 的值可以用于以下位置:

  • 非子查询、物化视图或者视图中的 SELECT 语句的选择列表中。
  • INSERT 语句中子查询的选择列表中。
  • INSERT 语句中的 VALUE 子句中。
  • UPDATE 语句中的 SET 子句中。

序列伪列 CURRVALNEXTVAL 的值不能用于以下位置:

  • DELETESELECT 或者 UPDATE 语句的子查询中。
  • 视图或者物化视图的查询中。
  • DISTINCT 运算符的 SELECT 语句中。
  • GROUP BY 子句或者 ORDER BY 子句的 SELECT 语句中。
  • 与另一个 SELECT 语句通过 UNIONINTERSECT 或者 MINUS 集合运算符进行联合的 SELECT 语句中。
  • SELECT 语句的 WHERE 子句中。
  • CREATE TABLE 或者 ALTER TABLE 语句中列的 DEFAULT 值。
  • CHECK 约束的条件中。

如何使用序列伪列

创建序列时,需要明确其初始值和步长。第一次引用 NEXTVAL 将返回序列的初始值,后续对 NEXTVAL 的引用将按照上一次序列的返回值加上序列定义的步长后返回一个新值。任何时候对 CURRVAL 的引用,都将返回当前序列的值,即最后一次对 NEXTVAL 引用时返回的值。

在会话中引用序列的 CURRVAL 伪列前,都应首先应用序列的 NEXTVAL 伪列来初始化本次会话的序列值。

创建序列时,可以定义其初始值以及其值之间的增量。对 NEXTVAL 的第一次引用将返回序列的初始值。对 NEXTVAL 的后续引用将会使序列值按照定义的增量递增,并返回新值。任何对 CURRVAL 的引用总是返回该序列的当前值,即最后一次对 NEXTVAL 引用时返回的值。对序列的创建的相关内容,请参考文档 CREATE SEQUENCE 章节。

在单条 SQL 语句中引用 NEXTVAL 时,OceanBase 按照以下方式递增序列:

  • SELECT 语句的外部查询块每返回一行递增一次。这类查询块可以出现在以下地方:

  • 顶层 SELECT 语句。

  • INSERT... SELECT 语句。对于多表插入,NEXTVAL 必须位于 VALUES 子句中,子查询每返回一行序列就递增一次,即使多个分支引用了 NEXTVAL
  • CREATE TABLE ... AS SELECT 语句。
  • CREATE MATERIALIZED VIEW ... AS SELECT 语句。

  • UPDATE 语句每更新一行序列就递增一次。

  • 每有一条包含 VALUES 子句的 INSERT 语句就递增一次。
  • MERGE 语句每合并一行序列递增一次。NEXTVAL 可以出现在 merge_insert_clause 或者 merge_update_clause 子句中,也可两者同时出现。NEXTVAL 会随着每一行的更新和插入而递增,即使序列数值没有用于更新或者插入操作。如果 NEXTVAL 在这些位置中被指定了多次,那么对应每一行都递增一次序列,而且该行中出现的所有 NEXTVAL 都返回相同的值。

当这些位置多次引用一个序列的 NEXTVAL 伪列时,该序列都只递增一次,即为所有被引用的 NEXTVAL 伪列返回当前序列的下一个序列值。

当这些位置同时引用一个序列的 CURRVALNEXTVAL 伪列时,OceanBase 将递增该序列,即为被引用的 CURRVALNEXTVAL 伪列都返回当前序列的下一个序列值。

序列可以同时被许多用户访问,不存在等待和锁定。

ROWSCN 伪列

ORA_ROWSCN 伪列将最新更改的系统更改号(SCN:System Change Number)反映到一行,该更改号表示这一行数据修改所在事务的提交时间。

ROWNUM 伪列

ROWNUM 伪列会对查询结果中的每一行进行编号,其值为该行在查询结果集中的具体位置。第一行返回值 1,第二行返回值 2,之后以此类推。

ROWNUM 的用法说明

ROWNUM 可以限制返回的行数,例如以下示例,将返回 employees 表中的 5 条数据:

  1. SELECT * FROM employees WHERE rownum <=5;

如果在 ROWNUM 后有 ORDER BY 子句,则将对满足 WHERE 条件句的结果进行重排序。如果将 ORDER BY 子句嵌入子查询中,并将 ROWNUM 伪列作为条件放置在顶级查询中,则可以强制 ROWNUM 条件在行排序之后执行。例如,使用以下语句查询年龄最大的 5 名员工信息是得不到预期结果的,该语句只是将查询结果中的前 5 条员工信息进行年龄排序:

  1. SELECT * FROM employees WHERE rownum <=5 ORDER BY age DESC;

正确的用法应该如下:

  1. SELECT * FROM (SELECT * FROM employees ORDER BY age DESC) WHERE rownum <= 5;

WHERE 子句中,指定 ROWNUM 大于任何一个正整数时总是返回 FALSE,例如以下 SQL 语句将不返回任何信息:

  1. SELECT * FROM employees WHERE rownum > 1;

因为在获得表的第一行结果时,改行的 ROWNUM 伪列值将被赋值为 1,此时在 WHERE 条件判断时结果为 FALSE,则此行被舍去。在获得第二行结果时,该行的 ROWNUM 伪列值任然被赋值为 1,WHERE 条件判断的结果依旧为 FALSE,此行再次被舍去。以此类推,所以所有行都不满足条件,因此不返回任何数据。

也可以通过 UPDATE 语句将ROWNUM 数值赋值给表中的某一列,例如:

  1. UPDATE employees SET id = rownum;

此语句将对表 employeesid 列进行 ROWNUM 赋值,即依次对 id 列赋值 1、2、… 直至该表总行数。

注意

在查询中使用 ROWNUM 可能会影响视图优化。