伪列(Pseudocolumn)的行为与表中的列相同,但并未存储具体数值。因此,伪列只具备读属性,您不可以对伪列进行插入、更新、删除的等行为。
层次查询伪列
层次查询伪列仅在层次查询中有效,要在查询中定义层次结构关系,必须使用 CONNECT BY
子句。
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
:返回序列的下一个自增值。
使用序列伪列时,必须在 CURRVAL
、NEXTVAL
前带上序列的名称,并用句点(.)引用。例如,序列的名称为 SEQ_FOO,则可以通过 SEQ_FOO.CURRVAL
获取 SEQ_FOO 序列的当前值。同样,可以通过 SEQ_FOO.NEXTVAL
获取 SEQ_FOO 序列的下一个自增值。
序列伪列的应用场景
序列伪列 CURRVAL
和 NEXTVAL
的值可以用于以下位置:
非子查询、物化视图或者视图中的
SELECT
语句的选择列表中。INSERT
语句中子查询的选择列表中。INSERT
语句中的VALUE
子句中。UPDATE
语句中的SET
子句中。
序列伪列 CURRVAL
和 NEXTVAL
的值不能用于以下位置:
DELETE
、SELECT
或者UPDATE
语句的子查询中。视图或者物化视图的查询中。
带
DISTINCT
运算符的SELECT
语句中。带
GROUP BY
子句或者ORDER BY
子句的SELECT
语句中。与另一个
SELECT
语句通过UNION
、INTERSECT
或者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
伪列返回当前序列的下一个序列值。
当这些位置同时引用一个序列的 CURRVAL
和 NEXTVAL
伪列时,OceanBase 将递增该序列,即为被引用的 CURRVAL
和 NEXTVAL
伪列都返回当前序列的下一个序列值。
序列可以同时被许多用户访问,不存在等待和锁定。
ROWSCN 伪列
ORA_ROWSCN
伪列将最新更改的系统更改号(SCN:System Change Number)反映到一行,该更改号表示这一行数据修改所在事务的提交时间。
ROWNUM 伪列
ROWNUM
伪列会对查询结果中的每一行进行编号,其值为该行在查询结果集中的具体位置。第一行返回值 1,第二行返回值 2,之后以此类推。
ROWNUM 的用法说明
ROWNUM
可以限制返回的行数,例如以下示例,将返回 employees 表中的 5 条数据:
SELECT * FROM employees WHERE rownum <=5;
如果在 ROWNUM
后有 ORDER BY
子句,则将对满足 WHERE
条件句的结果进行重排序。如果将 ORDER BY
子句嵌入子查询中,并将 ROWNUM
伪列作为条件放置在顶级查询中,则可以强制 ROWNUM
条件在行排序之后执行。例如,使用以下语句查询年龄最大的 5 名员工信息是得不到预期结果的,该语句只是将查询结果中的前 5 条员工信息进行年龄排序:
SELECT * FROM employees WHERE rownum <=5 ORDER BY age DESC;
正确的用法应该如下:
SELECT * FROM (SELECT * FROM employees ORDER BY age DESC) WHERE rownum <= 5;
在 WHERE
子句中,指定 ROWNUM
大于任何一个正整数时总是返回 FALSE,例如以下 SQL 语句将不返回任何信息:
SELECT * FROM employees WHERE rownum > 1;
因为在获得表的第一行结果时,改行的 ROWNUM
伪列值将被赋值为 1,此时在 WHERE
条件判断时结果为 FALSE,则此行被舍去。在获得第二行结果时,该行的 ROWNUM
伪列值任然被赋值为 1,WHERE
条件判断的结果依旧为 FALSE,此行再次被舍去。以此类推,所以所有行都不满足条件,因此不返回任何数据。
也可以通过 UPDATE
语句将ROWNUM
数值赋值给表中的某一列,例如:
UPDATE employees SET id = rownum;
此语句将对表 employees 的 id 列进行 ROWNUM
赋值,即依次对 id 列赋值 1、2、… 直至该表总行数。
注意
在查询中使用 ROWNUM
可能会影响视图优化。
ROWID 伪列
ROWID 伪列提供了快速定位表中某一行的能力,ROWID 值由主键编码得到,不会进行实际的存储,类型是 UROWID。使用方法如下:
从 employees 表中查询到 ROWID 值
obclient> SELECT ROWID, last_name FROM employees WHERE department_id = 20;
+-------------------+-----------+
| ROWID | LAST_NAME |
+-------------------+-----------+
| *AAIKAQAAAAAAAAA= | xxx |
+-------------------+-----------+
1 row in set (0.01 sec)
使用 ROWID 值进行 update 操作
obclient> UPDATE employees SET last_name = 'yyy' WHERE ROWID = '*AAIKAQAAAAAAAAA=';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
obclient> select last_name, department_id from employees;
+-----------+---------------+
| LAST_NAME | DEPARTMENT_ID |
+-----------+---------------+
| yyy | 20 |
+-----------+---------------+
1 row in set (0.01 sec)