10g树形查询新特性CONNECT_BY_ISCYCLE的9i实现方式(一)
上一篇 / 下一篇 2008-07-20 23:56:28 / 个人分类:ORACLE
在
这一篇描述一下解决问题的思路。
CONNECT_BY_ISCYCLE的实现和前面两篇文章中CONNECT_BY_ROOT和CONNECT_BY_ISLEAF的实现完全不同。
因为要实现CONNECT_BY_ISCYCLE,就必须先实现CONNECT BY NOCYCLE,而在9i中是没有方法实现这个功能的。
也就是说,首先要实现自己的树形查询的功能,而仅这第一点,就是一个异常困难的问题,何况后面还要实现NOCYCLE,最后再加上一个ISCYCLE的判断。
所以总的来说,这个功能的实现比前面两个功能要复杂得多。由于树形查询的LEVEL是不固定的,所以采用链接的方式实现,基本上是不现实的。换句话说,用纯SQL的方式来实现树形查询的功能基本上不可行。而为了解决这个功能,只能通过PL/SQL配合SQL来实现。
仍然是首先构造一个例子:
SQL> CREATE TABLE T_TREE (ID NUMBER, FATHER_ID NUMBER, NAME VARCHAR2(30));
表已创建。
SQL> INSERT INTO T_TREE VALUES (1, 0, 'A');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (2, 1, 'BC');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (3, 1, 'DE');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (4, 1, 'FG');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (5, 2, 'HIJ');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (6, 4, 'KLM');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (7, 6, 'NOPQ');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (0, 0, 'ROOT');
已创建1行。
SQL> INSERT INTO T_TREE VALUES (4, 7, 'FG');
已创建1行。
SQL> COMMIT;
提交完成。
SQL> SELECT * FROM T_TREE;
ID FATHER_ID NAME
ea@uO"[0---------- ---------- ------------------------------ITPUB个人空间-@KP!hq;[4`/P
1
2 1 BC
eB J p1Z1d?t1ME0 3 1 DEITPUB个人空间 l/y0JbD
4 1 FG
"s!i P3a5UT!G/R0 5 2 HIJ
8C(LK;x+k?j0 6 4 KLMITPUB个人空间P;T*En9c
7 6 NOPQ
"@"Y"l8Ml0 0 0 ROOTITPUB个人空间4^'cWy4sK
4 7 FG
已选择9行。
上面构造了两种树形查询循环的情况,一种是当前记录的自循环,另一种是树形查询的某个子节点是当前节点的祖先节点,从而构成了循环。在这个例子中,记录ID为0和ID为4且FATHER_ID等于7的两条记录分别构成了上述的两种循环的情况。
下面就来看看CONNECT_BY_ISCYCLE和CONNECT BY NOCYCLE的功能:
SQL> SELECT *
+V%U'k6b |3mT ~;PBx"F0 2 FROM T_TREE
%bQ*y"D}/Z$W;M0 3 START WITH ID = 0ITPUB个人空间V"bO:L}
u~2MOP[
4 CONNECT BY PRIOR ID = FATHER_ID;
'cV4EZ \kd0ERROR:
N s3mGN0k;zS0x`0ORA-01436:用户数据中的CONNECT BY循环
未选定行
SQL> SELECT *
#_1@3|KrD0 2 FROM T_TREEITPUB个人空间1}D1siK2fZ
CS:J
3 START WITH ID = 1
y
A8eyb&M0 4 CONNECT BY PRIOR ID = FATHER_ID;ITPUB个人空间1{8a{"O
`8Ck
ERROR:ITPUB个人空间
M6\!R:p.qe
ORA-01436:用户数据中的CONNECT BY循环
未选定行
这就是不使用CONNECT BY NOCYCLE的情况,查询会报错,指出树形查询中出现循环,在
SQL> SELECT *ITPUB个人空间-Tpg [U@"s
2 FROM T_TREEITPUB个人空间.e0QP&e@o
3 START WITH ID = 0
U:`RX*yR6a0 4 CONNECT BY NOCYCLE PRIOR ID = FATHER_ID;
ID FATHER_ID NAME
8y5s`'|%|zH!yZ0---------- ---------- ------------------------------
\a1bb HI0 0 0 ROOTITPUB个人空间gh)GB Q
1
d MY:p1h#M0 2 1 BCITPUB个人空间)ApsRK:J7{Ir-z,j
5 2 HIJ
-t
@h%B3]NUH%w;w0 3 1 DE
:NWD
Zq|u0 4 1 FG
U8iL%K-xdz1jG0 6 4 KLM
`'g$g$XBu0 7 6 NOPQ
已选择8行。
使用CONNECT BY NOCYCLE,Oracle自动避免循环的产生,将不产生循环的数据查询出来,下面看看CONNECT_BY_ISCYCLE的功能:
SQL> SELECT ID,ITPUB个人空间+EAG*Q,m%D{V
2 FATHER_ID,ITPUB个人空间\b
l,U+gQ*qg(i
3 NAME,ITPUB个人空间
]5yM(o'x
4 CONNECT_BY_ISCYCLE CYCLED