1. 程式人生 > >Oracle connect by level 小結(一)

Oracle connect by level 小結(一)

1. 準備測試用表

CREATE TABLE T  (ID VARCHAR2(10));
INSERT INTO T VALUES ('A');
INSERT INTO T VALUES ('B');
INSERT INTO T VALUES ('C');
COMMIT;
select * from t;
-- 準備一張一列三行的測試表

2. 簡單測試和解釋

select id,level from t connect by level<1;

  • 偽列level必須和connect by 一起使用
  • 本例討論的是 connect by level < h,而非 connect by level< = h(實際上就是相差1的區別)
  • 有些時候偽列level和rownum可以做替換使用
  • 該sql會生成樹形結構
  • t表中有N條資料,則生成N個子樹
  • 每個子樹有 h-1 層,即高度為 L=h-1,查出的資料中level的值最大為 h-1
  • sql查出來的記錄順序是生成的子樹以先根遍歷的順序
  • 當h為1或者2時,子樹的高度都為1(因為沒有高度為0的樹),SQL查詢結果就是t表的所有記錄

3. level大於3時的測試和解釋

select id,level from t connect by level<3;
-- 表t有3條記錄,N=3
-- 條件 level<3,L=2
-- 那麼會生成3棵高度為2的子樹,然後先根遍歷


  • 該SQL實際上生成了上圖所示的三棵子樹
  • 先根遍歷的結果就是SQL查出來的記錄順序

4. level大於4時的測試和解釋

select id,level from t connect by level<4;
-- 表t有3條記錄,N=3
-- 條件 level<4,L=3
-- 那麼會生成3棵高度為3的子樹,然後先根遍歷

5. 衍生出來的相關技巧

select level from dual connect by level<=5;
select level from dual connect by rownum<=5;
select rownum from
dual connect by rownum<=5;
select rownum from dual connect by level<=5; -- 有些時候偽列level和rownum可以做替換使用 -- 但並不是level和rownum完全一樣 select id, rownum, level from t connect by level < 5; select id, rownum, level from t connect by rownum < 5; -- 當表不是一行一列的dual時,是要慎用兩者的替換的 -- 這倆條SQL結果不在截圖展示,請自行測試

6. 技巧繼續衍生

select * from t,(select level from dual connect by level<=5);
-- 使用笛卡爾積,將原表複製出N份記錄

insert into t select * from t;
commit;
-- 相似的製造資料的方法
-- 重複幾次你的表就會爆炸掉
-- BOOOOOM!

7. 技巧再次衍生

該技巧的再次衍生,可以用於case列傳行的還原SQL,因為case的行列轉換及其還原系列博文還未釋出,請暫時參照《Oracle regexp_substr函式簡摘》中的樣例3的推演1和推演2,該博文的樣例3的推演實際上就是
case列傳行的還原SQL的推演。

8. 衍生出來的SQL炸彈

select level lvl
  from (select level lvl from dual connect by level <= n)
connect by level <= n;
-- 當n為5的時候記錄數為 3905
-- 當n為6的時候記錄數劇增為 55986
-- 7 的時候 55986
-- 8 的時候 19173960
-- 9 的時候... 我的測試庫出不來了親~

[TOC]