Oracle connect by level 小结(一)

  • Post author:
  • Post category:其他


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]



版权声明:本文为zwjzqqb原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。