1.层次查询环的判断
1.1 环的出现
层次查询中的环指的是作为某一行数据祖先结点的行又作为该行的子结点出现的情况。下面,我们通过一个例子来说明层次查询中环的出现,建立如下数据:
| create table t1(parent int,value int); insert into t1 values(1,2); insert into t1 values(2,3); insert into t1 values(2,4); insert into t1 values(3,5); insert into t1 values(3,6); insert into t1 values(5,2); |
按照如下层次查询语句的连接条件,表t1的数据可以组成如图1的结构。
| select * from t1 connect by prior value=parent start with value=2; |

图1 t1数据的层次结构
如图1所示,根据连接条件prior value = parent,作为(5,2)祖先结点的数据行(2,3)又作为其子结点出现,这样就形成了环;而(2,4)虽然与(2,3)同是(1,2)的子结点,但由于不是(5,2)的直接祖先,所以作为其子结点出现也并不能形成环。
利用上述层次查询语句进行查询,结果报错。
1.2 Oracle中判断环的标准分析
按照环的定义,逻辑上很容易进行环的判断,但是层次查询可以通过NOCYCLE关键字来屏蔽掉形成环的数据;CONNECT_BY_ISCYCLE伪列在当前行的祖先结点又出现在其子结点时返回1,所以我们需要进一步研究层次查询中形成环的标准。
下面通过NOCYCLE关键字和CONNECT_BY_ISCYCLE、LEVEL等伪列来研究Oracle层次查询出现环的判断。
对上一节表t1的数据,进行如下查询:
| Select level, connect_by_iscycle,connect_by_isleaf,parent, value From t1 Connect by nocycle prior value = parent Start with parent =1; |
查询的结果为:
| LEVEL CONNECT_BY_ISCYCLE CONNECT_BY_ISLEAF PARENT VALUE ---------- ------------------ ----------------- ---------- ---------- 1 0 0 1 2 2 0 0 2 3 3 1 1 3 5 3 0 1 3 6 2 0 1 2 4 |
由结果来看,元组(3,5)的CONNECT_BY_ISCYCLE的值为1,屏蔽掉了其子结点(5,2),而(5,2)并没有出现在其祖先结点中,但(5,2)的VALUE列的值2在其祖先结点(1,2)中已经出现过了。
由此推断,Oracle中层次查询的环的判断标准并不是判断子结点整个元组是否出现在祖先元组中,而是根据连接条件中表示父结点的PRIOR关键字标注的表达式的值是否在祖先结点中出现来进行判断的。
2.层次查询过滤条件的处理
层次查询语法中,使用WHERE语句来对层次查询的结果进行过滤,本节将就层次查询语句中的WHERE语句的处理进行分析。
2.1 单表层次查询过滤条件的处理
对单表进行层次查询时,WHERE语句只负责过滤数据,在得到层次查询的结果集进行判断,将满足WHERE语句指定的逻辑表达式的元组返回。
2.2 多表层次查询过滤条件的处理
对多表进行层次查询,层次查询的直接对象是多个表连接之后的数据集。而WHERE语句中的逻辑表达式如何处理是个问题。有两种合理的处理方式:
WHERE语句不进行特殊的处理,以所有表的笛卡儿集为层次查询的对象,然后将WHERE语句作为过滤层次查询后的过滤条件。
对WHERE语句中的逻辑表达式进行处理,根据相应的策略将where语句中的一部分逻辑表达式作为连接条件下放的层次查询下层的连接中去。这样的话层次查询的直接对象是以连接条件选择的笛卡儿集的一部分数据。而余下的逻辑表达式继续作为过滤条件对层次查询的结果集进行过滤。
也就是对例如 select * from t1,t2 where t1.f1=t2.c1 connect by prior t1.f1=t1.f2这样的语句。决定层次查询的直接对象到底是t1×t2 还是σt1.f1=t2.c1(t1×t2)的问题。下面利用如下数据就WHERE语句逻辑表达式的各种情况对Oracle的实现进行研究。
表t1:
| Drop table t1; Create table t1( a int, p int, c int); Insert into t1 values(0,0,1); Insert into t1 values(0,1,11); Insert into t1 values(0,11,111); Insert into t1 values(1,0,1); Insert into t1 values(1,1,11); Insert into t1 values(1,11,111); |
表t2:
| Drop table t2; Create table t2( a int); Insert into t2 values(0); Insert into t2 values(1); |
简单情况1
利用如下语句来分析当WHERE所有子逻辑表达式都只涉及一个表的情况。
语句1:
| Select level, sys_connect_by_path(t2.a,'/') path_a2, sys_connect_by_path(t1.a,'/') path_a1, sys_connect_by_path(p,'/') path_p, sys_connect_by_path(c,'/') path_c,t2.a,t1.a,p,c from t1,t2 where t1.a=1 connect by prior c=p start with p=0 and t1.a=1 and t2.a=0; |
查询的结果为:
|
LEVEL
|
PATH_A2
|
PATH_A1
|
PATH_P
|
PATH_C
|
A
|
A
|
P
|
C
|
|
1
|
/0
|
/1
|
/0
|
/1
|
0
|
1
|
0
|
1
|
|
3
|
/0/0/1
|
/1/0/1
|
/0/1/11
|
/1/11/111
|
1
|
1
|
11
|
111
|
|
3
|
/0/0/0
|
/1/0/1
|
/0/1/11
|
/1/11/111
|
0
|
1
|
11
|
111
|
|
3
|
/0/1/1
|
/1/0/1
|
/0/1/11
|
/1/11/111
|
1
|
1
|
11
|
111
|
|
3
|
/0/1/0
|
/1/0/1
|
/0/1/11
|
/1/11/111
|
0
|
1
|
11
|
111
|
|
2
|
/0/1
|
/1/1
|
/0/1
|
/1/11
|
1
|
1
|
1
|
11
|
|
3
|
/0/1/1
|
/1/1/1
|
/0/1/11
|
/1/11/111
|
1
|
1
|
11
|
111
|
|
3
|
/0/1/0
|
/1/1/1
|
/0/1/11
|
/1/11/111
|
0
|
1
|
11
|
111
|
|
2
|
/0/0
|
/1/1
|
/0/1
|
/1/11
|
0
|
1
|
1
|
11
|
|
3
|
/0/0/1
|
/1/1/1
|
/0/1/11
|
/1/11/111
|
1
|
1
|
11
|
111
|
|
3
|
/0/0/0
|
/1/1/1
|
/0/1/11
|
/1/11/111
|
0
|
1
|
11
|
111
|



评论加载中…
