3.2.9.7. DM
3.2.9.7.1. 层次查询伪列
层次查询伪列仅在层次查询中有效,要在查询中定义层次结构关系,必须使用 CONNECT BY 子句。
3.2.9.7.1.1. LEVEL 伪列
LEVEL 伪列用来协助标记节点的层次。
在层次结构中,根为第 1 层,根的子结点为第 2 层,之后以此类推。例如,根节点的 LEVEL 值会返回 1,根节点的子节点的 LEVEL 值会返回 2,之后以此类推。
以四层级倒置树结构为例,Root Row 是倒置树中最高的行,LEVEL 值一般为 1。Child Row 是任何非 Root Row,LEVEL 值一般为 2、3 或 4。Parent Row 是任何有 Child Row 的行(Root Row 除外),LEVEL 值一般为 2 或 3。Leaf Row 是任何没有孩子节点的行,LEVEL 值一般为 4。
-- 转换前Oracle SQL: select level from dual connect by level <= 10; LEVEL| -----+ 1| 2| 3| 4| 5| 6| 7| 8| 9| 10| -- 转换后DM SQL: SELECT level FROM dual CONNECT BY level<=10 level| -----+ 1| 2| 3| 4| 5| 6| 7| 8| 9| 10|
3.2.9.7.2. 序列伪列
序列(Sequence)是数据库按照一定规则生成的自增数字序列。因其自增的特性,通常被用作主键和唯一键。本节主要介绍序列的取值方法和应用场景。
3.2.9.7.3. 序列的取值方法
可以使用如下伪列引用 SQL 语句中的序列值:
CURRVAL:返回序列的当前值。
NEXTVAL:返回序列的下一个自增值。
使用序列伪列时,必须在 CURRVAL 和 NEXTVAL 前带上序列的名称,并用句点(.)引用。例如,序列的名称为 SEQ_FOO,则可以通过 SEQ_FOO.CURRVAL 获取 SEQ_FOO 序列的当前值。同样,可以通过 SEQ_FOO.NEXTVAL 获取 SEQ_FOO 序列的下一个自增值。
3.2.9.7.4. 序列值的应用场景
通过 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 约束的条件中。
带 FROM TABLE 语句中。
-- 创建sequence create sequence uni_seq increment by 1 start with 1; -- 转换前Oracle SQL: -- 获取下一个sequence的值 SELECT uni_seq.nextval FROM DUAL; NEXTVAL| -------+ 1| -- 转换后达梦 创建sequence SQL: create sequence uni_seq increment by 1 start with 1 -- 转换后达梦 SQL: SELECT uni_seq.nextval FROM DUAL nextval| -------+ 1|
3.2.9.7.5. ROWID 伪列
ROWID 伪列提供了快速定位表中某一行的能力,ROWID 值由主键编码得到,不会进行实际的存储。
-- 转换前Oracle SQL: SELECT ROWID,ke.* FROM unisql_employee ke; ROWID |EMPLOYEE_ID|NAME |SALARY|DEPARTMENT_ID|HIRE_DATE |COMMISSION_PCT| ------------------+-----------+-----+------+-------------+----------+--------------+ AAA2fQAAMAAIbD0AAA| 1|JACK | 5000| 1|2023-01-01| 0.05| AAA2fQAAMAAIbD0AAB| 2|TOM | 10000| 1|2023-02-01| 0.15| AAA2fQAAMAAIbD0AAC| 3|LINDA| 15000| 1|2023-03-01| 0.2| AAA2fQAAMAAIbD0AAD| 4|ADA | 20000| 2|2023-04-01| 0.1| AAA2fQAAMAAIbD0AAE| 5|TINA | 30000| 2|2023-05-01| 0.2| AAA2fQAAMAAIbD0AAF| 6|KATE | 50000| 3|2023-06-01| 0.3| -- 转换后达梦 SQL: SELECT ROWID,ke.* FROM unisql_employee ke ROWID|employee_id|name |salary|department_id|hire_date |commission_pct| -----+-----------+-----+------+-------------+----------+--------------+ 1| 1|JACK | 5000| 1|2023-01-01| 0.05| 2| 2|TOM | 10000| 1|2023-02-01| 0.15| 3| 3|LINDA| 15000| 1|2023-03-01| 0.2| 4| 4|ADA | 20000| 2|2023-04-01| 0.1| 5| 5|TINA | 30000| 2|2023-05-01| 0.2| 6| 6|KATE | 50000| 3|2023-06-01| 0.3|
3.2.9.7.6. ROWNUM 伪列
ROWNUM 伪列会对查询结果中的每一行进行编号,其值为该行在查询结果集中的具体位置。例如,第一行返回值 1,第二行返回值 2,之后以此类推。
统一SQL 支持以下ROWNUM的用法:
-- 转换前Oracle SQL: SELECT ke.*, ROWNUM AS row_num FROM unisql_employee ke; EMPLOYEE_ID|NAME |SALARY|DEPARTMENT_ID|HIRE_DATE |COMMISSION_PCT|ROW_NUM| -----------+-----+------+-------------+----------+--------------+-------+ 1|JACK | 5000| 1|2023-01-01| 0.05| 1| 2|TOM | 10000| 1|2023-02-01| 0.15| 2| 3|LINDA| 15000| 1|2023-03-01| 0.2| 3| 4|ADA | 20000| 2|2023-04-01| 0.1| 4| 5|TINA | 30000| 2|2023-05-01| 0.2| 5| 6|KATE | 50000| 3|2023-06-01| 0.3| 6| -- 转换后DM SQL: SELECT ke.*,ROWNUM AS row_num FROM unisql_employee AS ke employee_id|name |salary|department_id|hire_date |commission_pct|row_num| -----------+-----+------+-------------+----------+--------------+-------+ 1|JACK | 5000| 1|2023-01-01| 0.05| 1| 2|TOM | 10000| 1|2023-02-01| 0.15| 2| 3|LINDA| 15000| 1|2023-03-01| 0.2| 3| 4|ADA | 20000| 2|2023-04-01| 0.1| 4| 5|TINA | 30000| 2|2023-05-01| 0.2| 5| 6|KATE | 50000| 3|2023-06-01| 0.3| 6| -- 转换前Oracle SQL: SELECT rownum,employee_id,SALARY FROM unisql_employee ke WHERE rownum < 5; ROWNUM|EMPLOYEE_ID|SALARY| ------+-----------+------+ 1| 1| 5000| 2| 2| 10000| 3| 3| 15000| 4| 4| 20000| -- 转换后DM SQL: SELECT rownum,employee_id,SALARY FROM unisql_employee AS ke WHERE rownum<5 rownum|employee_id|salary| ------+-----------+------+ 1| 1| 5000| 2| 2| 10000| 3| 3| 15000| 4| 4| 20000| -- 转换前Oracle SQL: SELECT rownum,employee_id,SALARY FROM unisql_employee ke WHERE rownum <= 5; ROWNUM|EMPLOYEE_ID|SALARY| ------+-----------+------+ 1| 1| 5000| 2| 2| 10000| 3| 3| 15000| 4| 4| 20000| 5| 5| 30000| -- 转换后DM SQL: SELECT rownum,employee_id,SALARY FROM unisql_employee AS ke WHERE rownum<=5 rownum|employee_id|salary| ------+-----------+------+ 1| 1| 5000| 2| 2| 10000| 3| 3| 15000| 4| 4| 20000| 5| 5| 30000| -- 转换前Oracle SQL: SELECT employee_id,SALARY FROM unisql_employee ke WHERE rownum = 1; EMPLOYEE_ID|SALARY| -----------+------+ 1| 5000| -- 转换后DM SQL: SELECT employee_id,SALARY FROM unisql_employee AS ke WHERE rownum=1 employee_id|salary| -----------+------+ 1| 5000| -- 转换前Oracle SQL: SELECT * FROM (SELECT row_.*,rownum rownum_ FROM unisql_employee row_) WHERE rownum_ > 2 AND rownum_ <= 4; EMPLOYEE_ID|NAME |SALARY|DEPARTMENT_ID|HIRE_DATE |COMMISSION_PCT|ROWNUM_| -----------+-----+------+-------------+----------+--------------+-------+ 3|LINDA| 15000| 1|2023-03-01| 0.2| 3| 4|ADA | 20000| 2|2023-04-01| 0.1| 4| -- 转换后DM SQL: SELECT * FROM (SELECT row_.*,rownum AS rownum_ FROM unisql_employee AS row_) AS uni_sub WHERE rownum_>2 AND rownum_<=4 employee_id|name |salary|department_id|hire_date |commission_pct|rownum_| -----------+-----+------+-------------+----------+--------------+-------+ 3|LINDA| 15000| 1|2023-03-01| 0.2| 3| 4|ADA | 20000| 2|2023-04-01| 0.1| 4| -- 转换前Oracle SQL: SELECT * FROM (SELECT row_.*,rownum rownum_ FROM (select employee_id,salary,name from unisql_employee) row_) WHERE rownum_ > 2 AND rownum_ <= 4; EMPLOYEE_ID|SALARY|NAME |ROWNUM_| -----------+------+-----+-------+ 3| 15000|LINDA| 3| 4| 20000|ADA | 4| -- 转换后DM SQL: SELECT * FROM (SELECT row_.*,rownum AS rownum_ FROM (SELECT employee_id,salary,name FROM unisql_employee) AS row_) AS uni_sub WHERE rownum_>2 AND rownum_<=4 employee_id|salary|name |rownum_| -----------+------+-----+-------+ 3| 15000|LINDA| 3| 4| 20000|ADA | 4|