如果表中含有层次数据,可以通过使用层次查询有序地查看层次数据。

语法:

condition:指一个或多个表达式和逻辑(布尔)运算符的组合,并返回TRUE、FALSE或UNKNOWN
start with:指定层次查询的根数据行
connect by:指明父行和子行之间的关系:
  (1)nocycle:nocycle参数指示数据库返回查询的结果行,即使数据中存在connect by循环。nocycle参数和connect_by_iscycle伪列一起使用,可以查看哪些行数据包含循环。
  (2)一个层次查询中,condition中的每个表达式必须有一个prior关键字来限定指向父行。比如:

... PRIOR expr = expr
or
... expr = PRIOR expr

如果connect by是组合条件,只有一个条件需要prior操作符;尽管可以使用多个prior操作符。比如:

CONNECT BY last_name != 'King' AND PRIOR employee_id = manager_id ...
CONNECT BY PRIOR employee_id = manager_id and
PRIOR account_mgr_id = customer_id ...

prior是一元操作符,和算数操作符"+"、"-"有相同的优先级。prior根据层级查询中的表达式立刻计算出当前行的父行。

prior常用于比较等值操作比较列值(prior关键字可以出现在等值(=)操作符任意一侧)。prior指示oracle使用父行在该列上的值。理论上讲,除了等值(=)操作符,其它任意操作符也是可能出现在connect by语句中,但是这些操作符创建的条件可能会导致无限循环,运行时oracle会检测死循环并返回error消息。

connect by条件和prior表达式可以使用使用非相关子查询。但是prior表达式不可以使用sequence,因为currval和nextval在prior表达式中是无效。

可以使用connect_by_root进一步定义层次查询,不仅返回当前行的父行,还返回所有祖先行。

Oracle处理层次查询的过程:
1.如果有join操作,首先执行join操作,无论join出现在from后还是出现在where后
2.执行connect by条件
3.执行其他where条件
4.使用1-3的结果形成层次结果:
  (1)选择根结果行,根结果行要满足start with条件
  (2)选择每个根行的子行,子行要满足connect by条件
  (3)继续选择子行的子行
  (4)如果查询包含where子句,但是没有join操作。oracle会排除所有不满足where语句的行。oracle是逐行比较这些行,而不是直接移除不满足条件行的子行。
  (5)按照下图的方式返回有序的结果

       

为了找到父行的子行,oracle会对表中的行计算父行的connect by条件的prior表达式以及其他表达式,满足条件的就是子行。connect by条件中可以包含其它的条件来过滤满足查询的行。

如果connect by条件导致了层次循环产生了循环,oracle会返回一个error。

在层次查询中,不要指定order by 或者group by子句,因为connect by会打乱他们的顺序。如果想排序同一个父行的子行,可以使用order siblings by子句。

connect by示例:

SQL> select empno,ename,mgr from emp connect by empno= prior mgr;

     EMPNO ENAME             MGR
---------- ---------- ----------
7369 SMITH 7902
7902 FORD 7566
7566 JONES 7839
7839 KING
7499 ALLEN 7698
7698 BLAKE 7839
7839 KING
7521 WARD 7698
7698 BLAKE 7839
7839 KING
7566 JONES 7839
7839 KING
7654 MARTIN 7698
7698 BLAKE 7839
7839 KING
7698 BLAKE 7839
7839 KING
7782 CLARK 7839
7839 KING
7788 SCOTT 7566
7566 JONES 7839
7839 KING
7839 KING
7844 TURNER 7698
7698 BLAKE 7839
7839 KING
7876 ADAMS 7788
7788 SCOTT 7566
7566 JONES 7839
7839 KING
7900 JAMES 7698
7698 BLAKE 7839
7839 KING
7902 FORD 7566
7566 JONES 7839
7839 KING
7934 MILLER 7782
7782 CLARK 7839
7839 KING 39 rows selected. SQL> select empno,ename,mgr from emp connect by prior empno= mgr; EMPNO ENAME MGR
---------- ---------- ----------
7788 SCOTT 7566
7876 ADAMS 7788
7902 FORD 7566
7369 SMITH 7902
7499 ALLEN 7698
7900 JAMES 7698
7844 TURNER 7698
7654 MARTIN 7698
7521 WARD 7698
7934 MILLER 7782
7876 ADAMS 7788
7566 JONES 7839
7788 SCOTT 7566
7876 ADAMS 7788
7902 FORD 7566
7369 SMITH 7902
7782 CLARK 7839
7934 MILLER 7782
7698 BLAKE 7839
7499 ALLEN 7698
7900 JAMES 7698
7844 TURNER 7698
7654 MARTIN 7698
7521 WARD 7698
7369 SMITH 7902
7839 KING
7566 JONES 7839
7788 SCOTT 7566
7876 ADAMS 7788
7902 FORD 7566
7369 SMITH 7902
7782 CLARK 7839
7934 MILLER 7782
7698 BLAKE 7839
7499 ALLEN 7698
7900 JAMES 7698
7844 TURNER 7698
7654 MARTIN 7698
7521 WARD 7698 39 rows selected. SQL>

 

levle示例:

SQL> select empno,ename,mgr,level from emp connect by prior empno=mgr ;

     EMPNO ENAME             MGR      LEVEL
---------- ---------- ---------- ----------
7788 SCOTT 7566 1
7876 ADAMS 7788 2
7902 FORD 7566 1
7369 SMITH 7902 2
7499 ALLEN 7698 1
7900 JAMES 7698 1
7844 TURNER 7698 1
7654 MARTIN 7698 1
7521 WARD 7698 1
7934 MILLER 7782 1
7876 ADAMS 7788 1
7566 JONES 7839 1
7788 SCOTT 7566 2
7876 ADAMS 7788 3
7902 FORD 7566 2
7369 SMITH 7902 3
7782 CLARK 7839 1
7934 MILLER 7782 2
7698 BLAKE 7839 1
7499 ALLEN 7698 2
7900 JAMES 7698 2
7844 TURNER 7698 2
7654 MARTIN 7698 2
7521 WARD 7698 2
7369 SMITH 7902 1
7839 KING 1
7566 JONES 7839 2
7788 SCOTT 7566 3
7876 ADAMS 7788 4
7902 FORD 7566 3
7369 SMITH 7902 4
7782 CLARK 7839 2
7934 MILLER 7782 3
7698 BLAKE 7839 2
7499 ALLEN 7698 3
7900 JAMES 7698 3
7844 TURNER 7698 3
7654 MARTIN 7698 3
7521 WARD 7698 3 39 rows selected. SQL> select empno,ename,mgr,level from emp connect by empno= prior mgr ; EMPNO ENAME MGR LEVEL
---------- ---------- ---------- ----------
7369 SMITH 7902 1
7902 FORD 7566 2
7566 JONES 7839 3
7839 KING 4
7499 ALLEN 7698 1
7698 BLAKE 7839 2
7839 KING 3
7521 WARD 7698 1
7698 BLAKE 7839 2
7839 KING 3
7566 JONES 7839 1
7839 KING 2
7654 MARTIN 7698 1
7698 BLAKE 7839 2
7839 KING 3
7698 BLAKE 7839 1
7839 KING 2
7782 CLARK 7839 1
7839 KING 2
7788 SCOTT 7566 1
7566 JONES 7839 2
7839 KING 3
7839 KING 1
7844 TURNER 7698 1
7698 BLAKE 7839 2
7839 KING 3
7876 ADAMS 7788 1
7788 SCOTT 7566 2
7566 JONES 7839 3
7839 KING 4
7900 JAMES 7698 1
7698 BLAKE 7839 2
7839 KING 3
7902 FORD 7566 1
7566 JONES 7839 2
7839 KING 3
7934 MILLER 7782 1
7782 CLARK 7839 2
7839 KING 3 39 rows selected. SQL>

  

start with示例:

SQL> select ename,empno,mgr,level from emp start with empno = 7369 connect by prior empno=mgr order siblings by ename;

ENAME           EMPNO        MGR      LEVEL
---------- ---------- ---------- ----------
SMITH 7369 7902 1 SQL> select ename,empno,mgr,level from emp start with empno = 7369 connect by empno= prior mgr order siblings by ename; ENAME EMPNO MGR LEVEL
---------- ---------- ---------- ----------
SMITH 7369 7902 1
FORD 7902 7566 2
JONES 7566 7839 3
KING 7839 4 SQL>

  

Steven King是公司的头头,没有领导;John Russell是一名雇员,是部门80的头头
如果尝试将John Russell的改成King的领导,就会产生循环:

SQL> update employees set manager_id = 145
2 where employee_id = 100; 1 row updated. SQL> SELECT last_name "Employee",
2 LEVEL, SYS_CONNECT_BY_PATH(last_name, '/') "Path"
3 FROM employees
4 WHERE level <= 3 AND department_id = 80
5 START WITH last_name = 'King'
6 CONNECT BY PRIOR employee_id = manager_id AND LEVEL <= 4;
ERROR:
ORA-01436: CONNECT BY loop in user data no rows selected SQL>

  

nocycle关键字指示oracle继续返回数据,尽管有循环。connect_by_iscycle伪列指出哪行数据含有循环:

SQL> SELECT last_name "Employee", CONNECT_BY_ISCYCLE "Cycle",
2 LEVEL, SYS_CONNECT_BY_PATH(last_name, '/') "Path"
3 FROM employees
4 WHERE level <= 3 AND department_id = 80
5 START WITH last_name = 'King'
6 CONNECT BY NOCYCLE PRIOR employee_id = manager_id AND LEVEL <= 4
7 ORDER BY "Employee", "Cycle", LEVEL, "Path"; Employee Cycle LEVEL Path
------------------------- ---------- ---------- ----------------------------------------
Abel 0 3 /King/Zlotkey/Abel
Ande 0 3 /King/Errazuriz/Ande
Banda 0 3 /King/Errazuriz/Banda
Bates 0 3 /King/Cambrault/Bates
Bernstein 0 3 /King/Russell/Bernstein
Bloom 0 3 /King/Cambrault/Bloom
Cambrault 0 2 /King/Cambrault
Cambrault 0 3 /King/Russell/Cambrault
Doran 0 3 /King/Partners/Doran
Errazuriz 0 2 /King/Errazuriz
Fox 0 3 /King/Cambrault/Fox
Greene 0 3 /King/Errazuriz/Greene
Hall 0 3 /King/Russell/Hall
Hutton 0 3 /King/Zlotkey/Hutton
Johnson 0 3 /King/Zlotkey/Johnson
King 0 1 /King
King 0 3 /King/Partners/King
Kumar 0 3 /King/Cambrault/Kumar
Lee 0 3 /King/Errazuriz/Lee
Livingston 0 3 /King/Zlotkey/Livingston
Marvins 0 3 /King/Errazuriz/Marvins
McEwen 0 3 /King/Partners/McEwen
Olsen 0 3 /King/Russell/Olsen
Ozer 0 3 /King/Cambrault/Ozer
Partners 0 2 /King/Partners
Russell 1 2 /King/Russell
Sewall 0 3 /King/Partners/Sewall
Smith 0 3 /King/Cambrault/Smith
Smith 0 3 /King/Partners/Smith
Sully 0 3 /King/Partners/Sully
Taylor 0 3 /King/Zlotkey/Taylor
Tucker 0 3 /King/Russell/Tucker
Tuvault 0 3 /King/Russell/Tuvault
Vishney 0 3 /King/Errazuriz/Vishney
Zlotkey 0 2 /King/Zlotkey 35 rows selected. SQL>

  

Oracle - 层次查询的更多相关文章

  1. Oracle层次查询

    Oracle层次查询的语法如下: 下面根据两道“烧脑”的题具体来体现: 1. 根据时间先后顺序,十二星座的英文名称用逗号串起来为'Aries,Taurus,Gemini,Cancer,Leo,Virg ...

  2. 带您了解Oracle层次查询

    http://database.51cto.com/art/201010/231539.htm Oracle层次查询(connect by )是结构化查询中用到的,下面就为您介绍Oracle层次查询的 ...

  3. Oracle 层次查询 connect by

      oracle 层次查询 语法:       SELECT ... FROM            [WHERE condition]                             --过 ...

  4. 【转载】Oracle层次查询和分析函数

    摘要 一组连续的数,去掉中间一些数,如何求出剩下的数的区间(即号段)?知道号段的起止,如何求出该号段内所有的数?知道一个大的号段范围和已经取过的号段,如何求出可用的号段?利用Oracle提供的强大的查 ...

  5. Oracle层次查询和分析函数在号段选取中的应用

    转自:http://www.itpub.net/thread-719692-1-1.html 摘要一组连续的数,去掉中间一些数,如何求出剩下的数的区间(即号段)?知道号段的起止,如何求出该号段内所有的 ...

  6. Oracle层次查询start with connect by

    博客参考:https://www.cnblogs.com/jerryxing/articles/2339352.html start with connect by 层次查询(Hierarchical ...

  7. oracle层次查询的陷阱

    今天开发组同事找到我,说一个简单的层次查询非常慢,业务就是有一个存设备表连接关系的表,从node1连入,从node2连出,现在要找出node2的连出顺序,sql类似于: SELECT LEVEL ID ...

  8. 【转】 oracle 层次查询判断叶子和根节点

    Oracle 9i判断是叶子或根节点,是比较麻烦的一件事情,SQL演示脚本如下: DROP TABLE idb_hierarchical; create TABLE idb_hierarchical ...

  9. Oracle层次查询和with函数的使用

    开发中大家应该都做过什么类似部门管理这样的功能,一般情况下一个部门下面还有下一级部门(子部门),这个层级就类似一棵树.这种情况下一般会把父级部门和子级部门分成2个或者多个表,这种算是比较常规的做法:有 ...

随机推荐

  1. 使用Feign时报错Service id not legal hostname

    报错Service id not legal hostname的原因是服务名称不能带有下划线,可以使用中划线

  2. Linux实现多线程高速下载

    使用Wget下载,有时候速度挺慢的. 有没有好办法呢? 一.解决方案 安装axel 安装方法: yum -y install epel-release .el7.x86_64.rpm rpm -ivh ...

  3. 【Linux 驱动】Netfilter/iptables (八) Netfilter的NAT机制

    NAT是Network Address Translation的缩写,意即"网络地址转换". 从本质上来说,是通过改动IP数据首部中的地址,以实现将一个地址转换成还有一个地址的技术 ...

  4. Python学习笔记_05:使用Flask+MySQL实现用户登陆注册以及增删查改操作

    前言:本文代码参考自两篇英文博客,具体来源点击文末代码链接中文档说明. (PS:代码运行Python版本为2.7.14) 运行效果: 首页: 注册页面: 登陆界面: 管理员登陆后界面: 添加.删除.修 ...

  5. golang 垃圾回收机制

    用任何带 GC 的语言最后都要直面 GC 问题.在以前学习 C# 的时候就被迫读了一大堆 .NET Garbage Collection 的文档.最近也学习了一番 golang 的垃圾回收机制,在这里 ...

  6. 【Windows】XShell中使用小键盘和ALT键(作Meta键),使BackSpace正常

    小键盘: 打开终端的Session属性,VT模式,初始数字键盘模式,设置为普通 ALT键: 打开终端的Session属性,元(Meta)键仿真,将ALT用作Meta键 BackSpace: 打开终端的 ...

  7. MYSQL数据库注释

    //修改注释 alter table user comment = '我要修改注释'; //新建表设定表注释及解释说明. create table AuthUser( ID ) primary key ...

  8. JUC-线程八锁

    1,一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其它的线程都只能等待, 换句话说,某一个时刻内,只能有唯一一个线程去访 ...

  9. Qt5.9静态库编译VS2015-x64

    不多说. 编译配置参数如下 configure.bat -static -no-openssl -release 不支持OpenSSL,也没有安装各个数据库的Driver,所以数据库方面也只支持了SQ ...

  10. CentOS7统计某个进程当前的线程数

    方式一: cat /proc/[pid]/status 展示结果中,Threads后边对应的数字就是进程拥有的线程数量 方式二: |wc -l