Oracle Handbook系列之结构化查询

数据库 Oracle
这是这个系列的开篇之作,主要从结构化查询角度出发讲述Oracle的使用,本系列的其它文章会陆续录入,敬请期待...

一)准备测试数据

闲话少说,直入正题。建立一张简单的职工表 t_hierarchical:

  • Emp 职工编号
  • Mgr 职工的直接上司(Mgr本身也是职工)
  • Emp_name 职工姓名

插入一些测试数据,除了大老板AA,其它的职工都各有自己的Manager。

  1. select emp, mgr, emp_name from t_hierarchical t;
  1. 1            AA 
  2. 2     1     BB 
  3. 3     2     CC 
  4. 4     3     DD 
  5. 5     2     EE 
  6. 6     3     FF 

二)CONNECT BY

  1. select emp, mgr, LEVEL from t_hierarchical t 
  2. CONNECT BY PRIOR emp=mgr 
  3. order by emp; 
  4.  
  5. 1           1 
  6. 2     1     2 
  7. 2     1     1 
  8. 3     2     1 
  9. 3     2     3 
  10. 3     2     2 
  11. 4     3     4 
  12. 4     3     1 
  13. 4     3     2 
  14. 4     3     3 
  15. 5     2     3 
  16. 5     2     2 
  17. 5     2     1 
  18. 6     3     2 
  19. 6     3     3 
  20. 6     3     4 
  21. 6     3     1 

解释一下,CONNECT BY用于指定 父-子 记录的关系(PRIOR我们在下例中解释,更直观一些)。举emp 2为例,他隶属于emp 1,如果我们以emp 1为根节点,显然LEVEL=2;以emp 2自身为根节点,则LEVEL=1,这就是为什么上述查询结果中出现共色标识部分那两行记录,其它的类推。

三)START WITH

通常我们需要更直观、更具有实用性的结果,这需要用到结构化查询中的START WITH子句,用于指定根节点:

  1. select emp, mgr, LEVEL from t_hierarchical t 
  2. START WITH emp=1 
  3. CONNECT BY PRIOR emp=mgr; 
  4.  
  5. 1           1 
  6. 2     1     2 
  7. 3     2     3 
  8. 4     3     4 
  9. 6     3     4 
  10. 5         3 

这里我们指定了根节点是emp 1,这样的结果直观了许多,例如,以emp 1为根节点,那么emp 3位于第三级(emp 1—emp 2—emp 3),这里补充一下 PRIOR 关键字的说明,个人观点:“PRIOR emp=mgr”表示前一条记录的emp编号 = 当前记录的mgr编号,从查询结果中可以看出这一点。同时,从查询结果中还能发现明显的 递归 痕迹,参见不同颜色标识的数字。

四)SYS_CONNECT_BY_PATH()

不得不介绍一下非常牛波依的SYS_CONNECT_BY_PATH()函数,我们可以得到层次结构或者说树状结构的 路径, 参见如下:

  1. select emp, mgr, LEVEL, SYS_CONNECT_BY_PATH(emp,'/') path from t_hierarchical t 
  2. START WITH emp=1 
  3. CONNECT BY PRIOR emp=mgr; 
  4.  
  5. 1            1     /1 
  6. 2     1     2     /1/2 
  7. 3     2     3     /1/2/3 
  8. 4     3     4     /1/2/3/4 
  9. 6     3     4     /1/2/3/6 
  10. 5     2     3     /1/2/5 

五)CONNECT_BY_ISLEAF

非常好用的CONNECT_BY_ISLEAF虚列。何谓LEAF(叶子),即没有任何节点隶属于该节点:

  1. select emp, mgr, LEVEL, SYS_CONNECT_BY_PATH(emp,'/') path from t_hierarchical t 
  2. where CONNECT_BY_ISLEAF=1 
  3. START WITH emp=1 
  4. CONNECT BY PRIOR emp=mgr; 
  5.  
  6. 4     3     4     /1/2/3/4 
  7. 6     3     4     /1/2/3/6 
  8. 5     2     3     /1/2/5 

#p#

六)CONNECT BY与WHERE子句

下面再说说,关于引入结构化查询后,SQL语句的执行顺序问题,根据Oracle文档,先后是:

1)JOIN,无论用的是JOIN ON的写法,还是在WHERE中做的关联

2)CONNECT BY

3)其它的WHERE条件

看一个例子,假设上面的各位职工,需要保存一些注释信息,同时这些信息根据中文、英文分成两个不同版本,我们可以简单设计一下这个注释表:

  1. |-Emp 职工编号 
  2. |-Lang 语言(中文或英文) 
  3. |-Emp_desc 职工的具体描述 
  4.  
  5. select emp, lang, emp_desc from t_desc; 
  6.  
  7. 1     chinese 这是注释 
  8. 1     english   this is comment 
  9. 2     chinese 这是注释 
  10. 2     english   this is comment 
  11. 3     chinese 这是注释 
  12. 3     english   this is comment 
  13. 4     chinese 这是注释 
  14. 4     english   this is comment 
  15. 5     chinese 这是注释 
  16. 5     english   this is comment 
  17. 6     chinese 这是注释 
  18. 6     english   this is comment 

现在需要在原有的职工结构化查询中包括每个职工的中文注释信息,我们看看下面的查询:

  1. select t.emp, t.mgr, td.emp_desc, LEVEL 
  2. from t_hierarchical t, t_desc td 
  3. where t.emp=td.emp and td.lang='chinese' 
  4. START WITH t.emp=1 
  5. CONNECT BY PRIOR t.emp=t.mgr; 
  6.  
  7. 1            chinese 这是注释 1 
  8. 2     1     chinese 这是注释 2 
  9. 3     2     chinese 这是注释 3 
  10. 4     3     chinese 这是注释 4 
  11. 6     3     chinese 这是注释 4 
  12. 4     3     chinese 这是注释 4 
  13. 6     3     chinese 这是注释 4 
  14. 5     2     chinese 这是注释 3 
  15. 3     2     chinese 这是注释 3 
  16. 4     3     chinese 这是注释 4 
  17. 6     3     chinese 这是注释 4 
  18. 4     3     chinese 这是注释 4 
  19. 6     3     chinese 这是注释 4 
  20. 5     2     chinese 这是注释 3 
  21. 2     1     chinese 这是注释 2 
  22. 3     2     chinese 这是注释 3 
  23. 4     3     chinese 这是注释 4 
  24. 6     3     chinese 这是注释 4 
  25. 4     3     chinese 这是注释 4 
  26. 6     3     chinese 这是注释 4 
  27. 5     2     chinese 这是注释 3 
  28. 3     2     chinese 这是注释 3 
  29. 4     3     chinese 这是注释 4 
  30. 6     3     chinese 这是注释 4 
  31. 4     3     chinese 这是注释 4 
  32. 6     3     chinese 这是注释 4 
  33. 5     2     chinese 这是注释 3 

再看这个查询,看起来与前者是一样的:

  1. select t.emp, t.mgr, td.emp_desc, LEVEL 
  2. from t_hierarchical t join t_desc td 
  3. on (t.emp=td.emp and td.lang='chinese'
  4. START WITH t.emp=1 
  5. CONNECT BY PRIOR t.emp=t.mgr; 
  6.  
  7. 1            这是注释 1 
  8. 2     1     这是注释 2 
  9. 3     2     这是注释 3 
  10. 4     3     这是注释 4 
  11. 6     3     这是注释 4 
  12. 5     2     这是注释 3 

第二个是我们期望的结果,第二个则相去甚远。追究原因,是因为前一个例子中第二个条件 td.lang=’chinese’不被认为是JOIN条件,所以在CONNECT BY之后执行;后一个例子中由于显式地把第二个条件写在了JOIN ON子句中,所以它在CONNECT BY之前执行。

由于缺少第二个条件的JOIN(即本节***例)会导致每个的职工出现两次,换一个数据少一点的例子,看看CONNECT BY遇到这样的重复数据的时候是怎么处理的。

  1. select emp, mgr, lang from t2; 
  2.  
  3. 1            chinese 
  4. 1            english 
  5. 2     1     chinese 
  6. 2     1     english 

CONNECT BY之后:

  1. select emp, mgr, lang from t2 
  2. start with emp=1 
  3. connect by prior emp=mgr; 
  4.  
  5. 1            chinese 
  6. 2     1     chinese 
  7. 2     1     english 
  8. 1            english 
  9. 2     1     chinese 
  10. 2     1     english 

lang=’chinese’过滤之后:

  1. 1            chinese 
  2. 2     1     chinese 
  3. 2     1     chinese 

出现重复行,显然不是我们期望的结果。

七)CONNECT BY LEVEL

下面我再来看看一个特殊的用法 CONNECT BY LEVEL,这是一个理解起来令人头痛,但同时在某些情境下又是非常有用的:

  1. select LEVEL from dual CONNECT BY LEVEL<=6; 
  2.  

如果你以前从未使用过,但是不幸你猜中了结果,我深表佩服,我至今没有想通,事实上,它甚至不太符合结构化查询CONNECT BY的语法,因为根据Oracle文档,CONNECT BY条件中至少有一个表达式要使用PRIOR关键字。 以至于有人觉得CONNECT BY LEVEL是一个BUG,怀疑Oracle可能在后续的版本中加以纠正。

无论如何,CONNECT BY LEVEL在Oracle 10g/11g中运行良好,如果你不想费劲想通这其中的原由,可以简单地把想认为是构造了一个循环,因此如果你写成CONNECT BY 1=1,则会输出1到无穷大的数。

原文链接:http://www.cnblogs.com/KissKnife/archive/2011/02/25/1964816.html

 

【编辑推荐】

  1. SQL Server 2008 R2 SP1正式版发布
  2. Facebook对MySQL依赖的后果将是“比死还糟”
  3. 土法炮制数据库 家谱网帮你查祖宗
  4. 大数据时代已来临,你准备好了吗?

 

 

 

 

 

责任编辑:艾婧 来源: 侧身向南边的博客
相关推荐

2010-04-02 10:04:21

Oracle结构

2011-08-24 09:56:07

Oracle hand虚拟专用数据库VPD

2018-04-03 14:00:03

结构化数据非结构化数据数据库

2021-12-12 08:37:18

结构化数据非结构化数据数据

2023-12-25 15:00:18

结构化布线光纤

2024-05-27 00:32:45

2016-10-19 09:41:31

SQL查询语言关系型

2012-10-11 17:05:41

IBMdw

2012-02-08 15:54:05

ibmdw

2009-10-16 12:55:27

结构化布线系统

2009-10-21 15:20:28

结构化布线技术

2022-07-04 22:08:52

结构化数据谷歌

2009-10-15 13:49:23

结构化布线系统

2023-07-25 17:21:20

综合布线结构化布线

2011-03-01 09:39:51

结构化布线

2023-01-06 08:00:00

关系数据库数据库机器学习

2019-07-13 15:00:17

结构化SQLNOSQL数据库

2023-05-13 00:06:33

2015-12-18 10:10:06

集算器Java结构化

2015-12-08 13:53:56

java结构对齐连接
点赞
收藏

51CTO技术栈公众号