从 v2 开始,Oracle SQL 可以使用其专有的 CONNECT BY 语法进行分层查询。在他们最新的 11g 第 2 版中,他们添加了递归子查询分解,也称为递归 with 子句。这是 ANSI 标准,如果我理解正确的话,其他 RDBMS 供应商也已经实现了这一标准。
在将连接方式与递归方式进行比较时,我注意到使用循环检测时结果集有所不同。按结果连接对我来说更直观,所以我想知道 Oracle 的实现是否包含错误,或者这是否是标准 ANSI 和预期行为。因此,我的问题是您是否可以使用 MySQL、DB2、SQL Server 等其他数据库来检查递归查询。如果这些数据库当然支持递归 with 子句。
这是它在 Oracle 11.2.0.1.0 上的工作方式
SQL> select *
2 from t
3 /
ID PARENT_ID
---------- ----------
1 2
2 1
2 rows selected.
使用 CONNECT BY 语法的查询:
SQL> select id
2 , parent_id
3 , connect_by_iscycle
4 from t
5 connect by nocycle parent_id = prior id
6 start with id = 1
7 /
ID PARENT_ID CONNECT_BY_ISCYCLE
---------- ---------- ------------------
1 2 0
2 1 1
2 rows selected.
这对我来说很直观。然而,使用新的 ANSI 语法,它又返回一行:
SQL> with tr (id,parent_id) as
2 ( select id
3 , parent_id
4 from t
5 where id = 1
6 union all
7 select t.id
8 , t.parent_id
9 from t
10 join tr on t.parent_id = tr.id
11 ) cycle id set is_cycle to '1' default '0'
12 select id
13 , parent_id
14 , is_cycle
15 from tr
16 /
ID PARENT_ID I
---------- ---------- -
1 2 0
2 1 0
1 2 1
3 rows selected.
这是您可以用来检查的脚本:
create table t
( id number
, parent_id number
);
insert into t values (1, 2);
insert into t values (2, 1);
commit;
with tr (id,parent_id) as
( select id
, parent_id
from t
where id = 1
union all
select t.id
, t.parent_id
from t
join tr on t.parent_id = tr.id
) cycle id set is_cycle to '1' default '0'
select id
, parent_id
, is_cycle
from tr;