自从v2以来,Oracle sql可以使用其专有的CONNECT BY语法进行分层查询。在他们最新的11g版本2中,他们添加了递归子查询因子,也称为递归子句。这是ANSI标准,如果我理解正确,这个也已由其他RDBMS供应商实现。
将connect-by与递归with进行比较时,我注意到使用循环检测时结果集的差异。结果连接对我来说更直观,所以我想知道Oracle的实现是否包含错误,或者这是否是标准ANSI和预期行为。因此,我的问题是,如果您可以使用其他数据库(如MysqL,DB2,sql Server等)检查递归查询。如果这些数据库当然支持recursive 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;