Oracle 递归查询
来源:互联网 发布:淘宝全民疯抢怎么撤销 编辑:程序博客网 时间:2024/05/14 19:43
-- Start
递归查询的一个典型的例子是对树状结构的表进行查询,考虑如下的情况:
论坛首页--数据库开发----DB2------DB2 文章1--------DB2 文章1 的评论1--------DB2 文章1 的评论2------DB2 文章2----Oracle--Java 技术
以上是一个论坛的典型例子,下面我们新建一个表来存储以上信息。
CREATE TABLE BBS(PARENT_ID NUMBER(9, 0) NOT NULL,ID NUMBER(9, 0) NOT NULL,NAME VARCHAR2(200) NOT NULL -- 板块、文章、评论等。);INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (0,0,'论坛首页');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (0,1,'数据库开发');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (1,11,'DB2');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (11,111,'DB2 文章1');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (111,1111,'DB2 文章1 的评论1');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (111,1112,'DB2 文章1 的评论2');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (11,112,'DB2 文章2');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (1,12,'Oracle');INSERT INTO BBS (PARENT_ID,ID,NAME) VALUES (0,2,'Java 技术');
现在万事兼备了,我们开始查询吧。假设现在让你查询一下‘DB2 文章1’的所有评论,有人说,这还不简单,如下这样就可以了。
SELECT * FROM BBS WHERE PARENT_ID=(SELECT ID FROM BBS WHERE NAME='DB2');
答案完全正确。那么,现在让你查询一下DB2 的所有文章及评论,怎么办?传统的方法就很难查询了,这时候递归查询就派上用场了,如下:
SELECT-- LEVEL 是一个伪列,表示当前行所属层次,从 1 开始LEVEL,-- CONNECT_BY_ISLEAF 表示当前行是否是叶子节点。1 表示叶子节点,0 表示非叶子节点。CONNECT_BY_ISLEAF,-- CONNECT_BY_ROOT 是一个操作符,用来修饰列,表示该列的值是根节点的值。CONNECT_BY_ROOT NAME,-- SYS_CONNECT_BY_PATH 是一个函数,返回层次路径SYS_CONNECT_BY_PATH(NAME, '/')FROM BBS-- START WITH 用来表示起始行START WITH NAME = 'DB2'-- CONNECT BY 用来指定父子连接条件-- PRIOR 是一个操作符,用来修饰列,表示该列是父行中的列CONNECT BY PRIOR ID = PARENT_ID-- ORDER SIBLINGS BY 对同一层次中的行进行排序ORDER SIBLINGS BY NAME
结果如下:
10DB2/DB220DB2/DB2/DB2 文章131DB2/DB2/DB2 文章1/DB2 文章1 的评论131DB2/DB2/DB2 文章1/DB2 文章1 的评论221DB2/DB2/DB2 文章2
上面的例子比较完美,假设由于bug,导致数据变成下面这样。
论坛首页--数据库开发----DB2------DB2 文章1--------DB2 文章1 的评论1--------DB2 文章1 的评论2----------DB2 文章1
此时,我们执行上面的语句,Oracle 会抛出错误。你肯定很想知道到底是哪个记录出错了,呵呵,该怎么办呢?试一试下面的语句吧。
SELECT-- CONNECT_BY_ISCYCLE 是一个伪列,1 表示存在循环引用,否则为 0CONNECT_BY_ISCYCLE,NAMEFROM BBS-- NOCYCLE 指示 Oracle 出错不要停CONNECT BY NOCYCLE PRIOR ID = PARENT_ID
其实递归查询还有好多其他用途,如: 你想生成从 1 到 100 的数字,怎么办?看看下面的 SQL 吧。
SELECT ROWNUM FROM DUAL CONNECT BY ROWNUM <= 100;
再如:你想生成从 1 到 100 的数字,但是要求它们用逗号分割。
SELECT SYS_CONNECT_BY_PATH(R, ',') FROM (SELECT ROWNUM R FROM DUAL CONNECT BY ROWNUM <= 100)WHERE CONNECT_BY_ISLEAF = 1START WITH R = 1CONNECT BY R = PRIOR R + 1
当然,对于上面这个例子来说,上面的写法有点复杂,下面的写法更简单。
SELECT LISTAGG(R, ',') WITHIN GROUP (ORDER BY R)FROM (SELECT ROWNUM R FROM DUAL CONNECT BY ROWNUM <= 100)GROUP BY 1
--更多参见:Oracle SQL 精萃
-- 声明:转载请注明出处
-- Last edited on 2015-06-16
-- Created by ShangBo on 2015-06-16
-- End
0 0
- oracle递归查询
- oracle 递归查询
- ORACLE的递归查询
- oracle 递归查询
- Oracle 递归查询
- Oracle递归查询
- oracle 递归查询
- ORACLE递归查询
- Oracle 递归查询
- Oracle递归查询
- oracle树递归查询
- Oracle递归查询
- Oracle 中递归查询
- Oracle 递归查询
- Oracle 递归查询
- Oracle递归查询
- oracle递归查询
- ORACLE的递归查询
- 从新安装Zend studio,从新安装svn导致不能share项目的问题
- 队列的类模板
- Android数据存储之数据库的利用
- [转]maven常用命令
- 【限额300,预报从速!!!】首届中国移动测试大会将于7月11日在北京举行
- Oracle 递归查询
- 在Windows下用C扩展PHP(打包成dll)的方法
- android http协议post请求方式
- STL学习笔记之容器--map
- 两个日期之间差
- scrapy爬虫起步(1)--第一个爬虫程序
- GRE作文备考——创新者的八大特点
- Xamarin iOS教程之使用按钮接接收用户输入
- 获取Android设备唯一识别码