在 CONNECT BY 子句中的条件

在布尔条件和在一般的 SQL 表达式中,除了表达式和运算符是有效的之外,在 CONNECT BY 子句中指定的 condition 支持另外两种语法结构,仅在包括层级子句的 SELECT 语句中,PRIOR 运算符和 LEVEL 伪列才是有效的。

PRIOR 运算符

PRIOR 一元运算符可被包括在 CONNECT BY 子句中,以列名称作为它的运算对象。PRIOR 可用于将 CONNECT BY 子句的最近的先前递归步骤的结果的列引用,与对当前结果集的列引用区分开来。列名称紧跟在此右关联的运算符之后,如下列语法片断所示:
	CONNECT BY mgrid = PRIOR empid
此处,在 mgrid 中指定管理者的那些行满足 CONNECT BY 条件,在先前的迭代中与员工值相匹配的列在 empid 列中。
PRIOR 运算符可应用于比列名称更复杂的表达式。下列条件使用算术表达式作为 PRIOR 的运算对象:
	CONNECT BY PRIOR (salary - 10000) = salary

在同一 CONNECT BY 条件中,可以多次包括 PRIOR 运算符。另请参阅主题 层级查询子句,该主题提供一个在 CONNECT BY 子句的条件中使用 PRIOR 运算符的层级查询的示例。

LEVEL 伪列

伪列是与列名称共享同一命名空间的 SQL 的关键字,在某些其中的列表达式为有效的上下文中那是有效的。

LEVEL 是返回在返回了行的层级子句中迭代步骤的序号的伪列。对于由 START WITH 子句返回的所有行,LEVEL 返回值 1。通过应用 CONNECT BY 子句的第一个迭代返回的行返回 2。通过 CONNECT BY 的连续的迭代返回的行有增量为 1 的 LEVEL 值,因此 LEVEL = (N + 1) 表明为第 N 次 CONNECT BY 迭代返回的值。LEVEL 列的数据类型是 INTEGER。

下列层级查询的样例在 Projection 子句的选择列表中指定 LEVEL:
SELECT name, LEVEL FROM employee START WITH name = 'Goyal' 
   CONNECT BY PRIOR empid = mgrid;
该查询返回这些结果:
name          level

Goyal             1
Zander            2
McKeough          3
Barnes            3
Henry             2
O'Neil            3
Smith             3
Shoeman           3
Scott             2

9 row(s) retrieved.

在包括层级子句的 SELECT 语句的 Projection 子句中,以及在 CONNECT BY 子句的 condition 中,可包括 LEVEL。

然而,在下列上下文中,LEVEL 伪列不是有效的:
  • 没有 CONNECT BY 子句的 SELECT 语句
  • 层级子句的 START WITH condition
  • CONNECT_BY_ROOT 运算符的运算对象
  • SYS_CONNECT_BY_PATH 函数的参数。

仅在层级查询中有效的附加的语法

下列语法令牌支持层级查询,且仅在层级查询中是有效的。 然而,不同于 PRIOR 运算符和 LEVEL 伪列,它们在层级子句中不是有效的:
  • CONNECT_BY_ISCYCLE 伪列
  • CONNECT_BY_ISLEAF 伪列
  • CONNECT_BY_ROOT 一元运算符
  • SQL 的 SYS_CONNECT_BY_PATH( ) 函数。

CONNECT_BY_ISCYCLE 伪列

如果在层级中的下一级该行可能循环,则 CONNECT_BY_ISCYCLE 是返回 1 的伪列。即,该行有一个直接的孩子,该孩子又是在 CONNECT BY 子句中指定的搜索条件给出的祖先。如果该行不直接地导致循环,则该列返回 0。仅当在 CONNECT BY 子句中指定 NOCYCLE 时,才有可能为非 0 的值。此列的数据类型是 INTEGER。

下列 UPDATE 语句在 employee 表的数据层级中创建循环:

UPDATE employee SET mgrid = 5 WHERE empid = 17;

下列层级查询在 Projection 子句中包括 CONNECT_BY_ISCYCLE 伪列,但在它遇到 UPDATE 语句创建的循环的步骤中,CONNECT BY 子句抛出错误。

SELECT empid, 
       name, 
       mgrid, 
       CONNECT_BY_ISLEAF leaf, 
       CONNECT_BY_ISCYCLE cycle
FROM  employee
START WITH name = 'Goyal'
CONNECT BY  PRIOR empid = mgrid;

  665: Internal error on semantics - 
  CONNECT_BY_ISCYCLE is used without NOCYCLE parameter..
Error in line 1
Near character position 72

在它遇到 UPDATE 语句创建的循环的步骤中抛出错误的 CONNECT BY 子句中,通过指定 NOCYCLE,此查询可避免 -655 错误。

SELECT empid, name, mgrid, 
   CONNECT_BY_ISLEAF leaf, CONNECT_BY_ISCYCLE cycle
FROM employee
   START WITH name = 'Goyal'
   CONNECT BY NOCYCLE PRIOR empid = mgrid;

要获取此查询的结果,请参阅在主题 CONNECT BY 子句 中的对 NOCYCLE 关键字的描述的示例。

在下列上下文中,CONNECT_BY_ISCYCLE 伪列不是有效的:
  • 没有 CONNECT BY 子句的 SELECT 语句
  • START WITH 或 CONNECT BY 子句
  • CONNECT_BY_ROOT 运算符的运算对象
  • SYS_CONNECT_BY_PATH 函数的参数

CONNECT_BY_ISLEAF 伪列

如果该行如 CONNECT BY 所定义的那样是层级中的叶子,则 CONNECT_BY_ISLEAF 是返回 1 的伪列。如果节点在查询结果层级中(不是在实际的数据层级中)没有孩子,则该节点是叶节点。如果该行不是叶子,则该列返回 0。该列的数据类型是 INTEGER。

下列层级查询在 Projection 子句中指定 CONNECT_BY_ISLEAF 伪列,并声明 leaf 为那列的别名,在 DB-Access 中的结果集显示为:

SELECT empid, name, mgrid, CONNECT_BY_ISLEAF leaf
FROM emp1oyee
START WITH name = 'Goyal'
CONNECT BY PRIOR empid = mgrid;

      empid name             mgrid   leaf 

         16 Goyal               17      0
         14 Scott               16      1
         12 Henry               16      0
          9 Shoeman             12      1
          8 Smith               12      1
          7 O'Neil              12      1
         11 Zander              16      0
          6 Barnes              11      1
          5 McKeough            11      1

9 row(s) retrieved.

CONNECT_BY_ROOT 运算符

对于层级中的每行,CONNECT_BY_ROOT 一元运算符接受表达式作为它的运算对象,该表达式求值为层级的一个节点的行。CONNECT_BY_ROOT 返回它的运算对象的根祖先的表达式。
expression 运算对象可为任何 SQL 表达式,但它必须不包含任何层级查询令牌,包括下列令牌:
  • CONNECT_BY_ROOT 或 PRIOR 一元运算符
  • CONNECT_BY_ISCYCLE、CONNECT_BY_ISLEAF 或 LEVEL 伪列
  • SYS_CONNECT_BY_PATH 函数。
此右关联的运算符的返回数据类型是指定的表达式的数据类型。

下列示例中的层级查询从 employee 表返回行,既包括员工要向其直接地报告的管理者的标识编号,也包括位于此查询的层级的根的管理者的名称。

SELECT empid, name, mgrid, CONNECT_BY_ROOT name AS topboss
FROM employee
START WITH name = 'Goyal'
CONNECT BY PRIOR empid = mgrid;

      empid name             mgrid topboss    

         16 Goyal               17 Goyal     
         14 Scott               16 Goyal     
         12 Henry               16 Goyal     
          9 Shoeman             12 Goyal     
          8 Smith               12 Goyal     
          7 O'Neil              12 Goyal     
         11 Zander              16 Goyal     
          6 Barnes              11 Goyal     
          5 McKeough            11 Goyal     

9 row(s) retrieved.
在下列上下文中,CONNECT_BY_ROOT 运算符不是有效的:
  • 没有 CONNECT BY 子句的 SELECT 语句
  • START WITH 或 CONNECT BY 子句
  • SYS_CONNECT_BY_PATH 函数的参数

SYS_CONNECT_BY_PATH 函数

在包括层级子句的 SELECT 语句中调用 SYS_CONNECT_BY_PATH ( ) 函数是有效的,但不可从层级子句调用此函数。如果您尝试在 START WITH 或 CONNECT BY 子句的 condition 之内运行此函数,则 GBase 8s 返回错误。

在层级查询中,SYS_CONNECT_BY_PATH 函数可用来构建表示路径的字符串,该路径从对应于根节点的行至当前行。

这是 SYS_CONNECT_BY_PATH 的调用语法,返回在 LEVEL N 的指定行的字符串:
SYS_CONNECT_BY_PATH 函数
元素 描述 限制 语法
format_string 通常是作为运算符的常量字符串 用引号括起的字符串
string_expression 标识行的表达式。 不可包括层级查询令牌 表达式
SYS_CONNECT_BY_PATH 构建表示路径的字符串,通过递归地串联连续的返回值,该路径从根到该层级的 LEVEL N 的指定的行:
  • path1 := string_expression1||format_string 表示从第一个中间的结果集到根行的路径,
  • path2 := path1||string_expression2||format_string 求值为从根到在第二个中间的结果集中的行的路径,
  • . . .
  • pathN := path(N-1)||string_expressionN||format_string 求值为从根到第 N 个中间的结果集的路径。
SYS_CONNECT_BY_PATH 的参数中的表达式必须不包括任何层级查询结构,包括下列结构:
  • CONNECT_BY_ROOT 或 PRIOR 一元运算符
  • CONNECT_BY_ISCYCLE、CONNECT_BY_ISLEAF 或 LEVEL 伪列
  • SYS_CONNECT_BY_PATH 函数。
在参数列表中也无效的是聚集表达式。

从 SYS_CONNECT_BY_PATH ( ) 的返回值是 LVARCHAR(4000) 类型。

下列示例中的层级查询调用在 Projection 列表中的 SYS_CONNECT_BY_PATH 函数,以 employee.name 列和斜线(/)字符作为它的参数。

SELECT empid, name, mgrid, SYS_CONNECT_BY_PATH( name,'/') as hierarchy
   FROM employee
   START WITH name = 'Henry'
   CONNECT BY PRIOR empid = mgrid;

该查询返回数据层级的子集之内的行,其中在 START WITH 子句中指定 Henry 作为根,展现每一员工和员工的管理者的名称和 empid 编号,以及在该层级中到 Henry 的路径。CONNECT BY 子句使用相等断言 PRIOR empid = mgrid 来返回向管理者报告的员工(在此情况下,仅 Henry),通过先前的步骤返回了其 empid。该查询的结果集是:

empid      12
name       Henry
mgrid      16
hierarchy  /Henry 

empid      9
name       Shoeman
mgrid      12
hierarchy  /Henry/Shoeman 

empid      8
name       Smith
mgrid      12
hierarchy  /Henry/Smith 

empid      7
name       O'Neil
mgrid      12
hierarchy  /Henry/O'Neil 

4 row(s) retrieved.
这些行按检索它们的顺序罗列:
  • START WITH 子句在此层级的根返回了 Henry 行。
  • CONNECT BY 子句的第一个步骤返回了三行,对应于向 Henry 报告的三名员工。
  • 下一 CONNECT BY 步骤未返回行,因为由先前的步骤返回的 ShoemanSmithO'Neil 都是此层级之内的叶节点,对其 PRIOR empid = mgrid 条件求值为假。

查询执行结束,展示返回的四行,此处,hierarchy 是 SYS_CONNECT_BY_PATH( name,'/') 为每一行返回到 Henry 的路径的别名。(在第一个返回的行中,字符串 /Henry 展示 Henry 的根状态。)