1. 程式人生 > >oracle connect by從句中的

oracle connect by從句中的

在構造資料時,對於單行的基本資料來說,connect by levelconnect by rownum可以說是等效的。比如說下面的兩個語句的結果集是一樣的。

with tab1 as (
select 'a' id, 2 num from dual
)
select*from tab1
connect by level <= 2
;

with tab1 as (
select 'a' id, 2 num from dual
)
select*from tab1
connect by rownum <= 2
;
ID NUM
a 2
a 2

但是當基礎資料為多條時,rownum會產生不符合預期的結果。

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 4 num from dual
)
select id, num, rownum rn
  from tab1
connect by rownum <= 4
;
ID NUM RN
a 2 1
a 2 2
a 2 3
a 2 4
b 4 5

我明明指定了rownum <= 4,卻得到了5條記錄,這是怎麼回事?

我之後又寫了多條測試語句,最終的結論是:層次查詢中的rownum與最後結果集中的rownum並不是一個。

在層次查詢中,rownum被賦予的是層次查詢中返回的結果集的序號。第一個被查詢的根節點的rownum就是1,在此基礎上,下一條返回的資料為2,以此類推。當查出第四層時,查詢結束。至於多出來的第五條資料,可以這樣理解:connect語句的結果集由兩部分組成,即由start with查詢出的根節點與connect查詢出的子節點組成。根節點是不受connect從句約束的,所以當rownum <= 4生效後,其他根節點一併歸到了結果集中。又由於oracle的層次查詢是深度優先的,所以上面的例子中,實際查出的是一顆左斜樹。這就是查出4個a和1個b的原因。

用這個語句能更清晰的看出這些特點。

with
tab1 as ( select 'a' id, 2 num from dual union all select 'b' id, 2 num from dual union all select 'c' id, 4 num from dual ) select id, num, rownum rn, lpad('--', level * 3, '-') || level || '_' || id path from tab1 connect by rownum <= 4
ID NUM RN PATH
a 2 1 —1_a
a 2 2 ------2_a
a 2 3 ---------3_a
a 2 4 ------------4_a
b 2 5 —1_b
c 4 6 —1_c

在這個語句的基礎上加上where rownum <= 4確實也可以只查出4條資料。

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 2 num from dual union all
select 'c' id, 4 num from dual
)
select id, num, rownum rn, lpad('--', level * 3, '-') || level || '_' || id path
  from tab1
 where rownum <= 4
connect by rownum <= 4;

這樣可以保證只查出四條資料。

但是當語句的條件多一些後 比如這樣

with tab1 as (
select 'a' id, 2 num from dual union all
select 'b' id, 2 num from dual
)
select id, num, rownum rn, lpad('--', level * 3, '-') || level || '_' || id path
  from tab1
connect by rownum <= 6
and level <= 3
;
ID NUM RN PATH
a 2 1 —1_a
a 2 2 ------2_a
a 2 3 ---------3_a
b 2 4 ---------3_b
b 2 5 ------2_b
a 2 6 ---------3_a
b 2 7 —1_b

這是預料之中的結果,但是我實在想不出什麼樣的功能會用上這種語句…