导读:就爱阅读网友为大家分享了多篇关于 "递归查询" 资料,内容精辟独到,非常感谢网友的分享,希望从中能找到对您有所帮助的内容。
相关资料一 : ORACLE 中使用递归查询
在数据库查询中常常会碰到要查询树形结构的数据,需要用一个字段的数据当做下一条记录的父节点继续查询,如果在不知道有多少级节点的情况下一次次手写 SQL 查询会很繁琐而没有效率,这时可以使用 oracle 中的 connectwith prior 递归算法:Oracle 中 start with...connect by prior 子句用法 connect by 是结构化查询中用到的,其基本语法是:select ... from tablename start with 条件 1connect by 条件 2where 条件 3; 例:select * from tablestart with org_id = 'HBHqfWGWPy'connect by prior org_id =parent_id; 在实际使用时遇到两个问题,一是如果把 where 子句放在 start with...connectby... 子句后时会提示:ORA-00933:SQl 命令未完全结束。此时光标置于 where 处,如果将 where 放在 start with...connectby... 子句前则可以正常执行。二是查询的数据中不能有自循环,即例子中的 org_id 和 parent_id 在同一条记录中不能相等,否则会提示:ORA-01436: 用户数据中的 connectby 循环。这两点需要注意。补注:在遇到有循环的查询时,使用 connectbyNOCYCLEprior 就可以避免报错!以下是参考到的网络文档:
Oracle 数据库的递归查询用途非常的广泛,我们做递归查询首先要定义好递归函数,以及它的参数和返回值,然后实现查询。本文通过一个代码的实例讲解介绍了这一过程,接下来我们就开始介绍。
一、树型表结构:
节点 ID 上级 ID 节点名称
二、公式:
- select节点ID,
- 节点名称,
- level from表connectbyprior节点ID = 上级节点ID startwith上级节点ID = 节点值
说明:
1、常见的树形结构为公司组织机构、地区……
2、求节点 ID 以上的结构,或以上的结构,将 "节点 ID = 上级节点 ID" 左右顺序换一下即可。
3、Level 为 Oracle 的特殊字段,表示 "层" 的意思。当前节点 ID 的下一层节点为 "1"。
测试 SQL:
说明 1、求 002 以下 (或以上) 所有子节点和层次(动态: 总是从 1 开始算), 但不包括自身。
说明 2、如果求 002 以上的节点,则 "connect by prior topno=departno","=" 两边的条件换位即可。
- selectdepartno,
- departname,
- level fromdept connectbypriordepartno = topnostartwithtopno = '002';
测试数据:
- createtableDept(DepartNOvarchar2(10), DepartNamevarchar2(20), TopNovarchar2(10));
- insertintoDeptvalues('001', '董事会', '0');
- insertintoDeptvalues('002', '总裁办', '001');
- insertintoDeptvalues('003', '财务部', '001');
- insertintoDeptvalues('004', '市场部', '002');
- insertintoDeptvalues('005', '公关部', '002');
- insertintoDeptvalues('006', '销售部', '002');
- insertintoDeptvalues('007', '分销处', '006');
- insertintoDeptvalues('008', '业务拓展处', '004');
- insertintoDeptvalues('009', '销售科', '007');
向前查,比如:
- selectdistinctdepartno,
- departname,
- level fromdept connectbypriortopno = departnostartwith departno = '005';
那么其实是查 005 自身以及上级, 所以结果是 005,002,001。
总结:写递归最关键的要定义出来递归函数,递归函数最关键的要定义出来它的参数和它的返回值。参数最重要,分析一下参数怎么去定义? 这时候要分析递归的过程, 递归过程什么样呢? 根据它的 id 找它的父 id,根据它的父 id 找到它的孩子,根据它的孩子再找到它的孩子。那么分析这个参数肯定是一个 id,因为只有传进来 id,才知道怎么去找这个 id。
关于 Oracle 数据库的递归查询就介绍这么多,谢谢各位一直以来的支持!
Oracle 递归查询
1、创建表
建表语句:
插入数据:
INSERT INTO SC_DISTRICT(ID,NAME) VALUES(1,'四川省');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(2,1,'巴中市'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(3,1,'达州市');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(4,2,'巴州区'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(5,2,'通江县'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(6,2,'平昌县');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(7,3,'通川区'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(8,3,'宣汉县');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(9,8,'塔河乡'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(10,8,'三河乡'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(11,8,'胡家镇'); INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(12,8,'南坝镇');
INSERT INTO SC_DISTRICT(ID,PARENT_ID,NAME) VALUES(13,6,'大寨乡');
生成表如下:
查询某节点的所有子孙节点
查询指定节点的递归根节点
-- 本文章可以直接粘贴到 PLSQL 运行,测试表就自己创建吧
-- 测试名称:测试 oracle 递归
--oracle 版本:oracle8i
-- 样表:s_coalarea_test(地区表)
-- 表结构:国家 level(等级) 1 level 决定记录在树中的层次
-- 省份 level(等级) 2
-- 地区 level(等级) 3
-- 依次类推
-- 备注:这张地区表是一颗树,递归查询主要就是方便维护树
-- 测试 1:简单递归
-- 需求:根据地区名称查询其所有的下级地区名称
-- 备注:aid 是表主键,parentid 是父节点主键,areaname 地区名称
-- 分析:递归查询其实还是一个条件过滤
select s.areaname from s_coalarea_test s
start with --start with 是递归入口,也就是递归的起始位置 s.areaname ='黑龙江' -- 指明入口条件
connect by prior --prior 前序遍历 指明遍历方向 入不写 默认不递归查询
s.aid=s.parentid -- 级联条件 也就是你的树通过哪个字段相连的 顺序决定查询结果 须注意
-- 测试 2:谈递归入口 start with
-- 需求:根据多个地区名查询器所有下级地区
select s.areaname from s_coalarea_test s
start with
s.areaname ='黑龙江' -- 递归入口可以是多个值,其原理:先根据 start with 过滤记录 or -- 然后根据过滤后的记录,依次递归遍历结果
s.areaname='山西'
connect by prior
s.aid=s.parentid
-- 测试 3:再谈递归入口
-- 需求:根据多个地区名查询器所有下级地区
-- 错误:测试结果让人恼火,原来 start with 先于 where 执行,所以这个测试很失败,大家要注意
select s.areaname from s_coalarea_test s
where s.areaname='黑龙江'
or
s.areaname = '山西'
start with
s.areaname = s.areaname -- 既然 start with 只是过滤记录,那么当然我们也可以不在此处过滤,而直接用 where 过滤的结果了
connect by prior
s.aid=s.parentid
-- 测试 4:谈级联条件
-- 需求:根据地区名,查询上级地区
select s.areaname from s_coalarea_test s
start with
s.areaname='大同'
connect by prior
s.parentid=s.aid -- 注意,此时仅仅是级联条件顺序改变了
-- 总结:到底是查父节点还是子节点,有级联顺序决定
-- 规律:【本记录字段】=【连接字段】
-- 如本实例:是通过本记录的 parentid 匹配其他记录的 aid(主键)结
果是查父节点
-- 如顺序颠倒,则是:有本记录的 aid(主键)匹配其他记录的 parentid,结果是查子节点
-- 测试 5:递归关键字出现的位置
-- 需求:根据地区名称查找其所在省份
select s.areaname from s_coalarea_test s
where s.arealevel=1 -- 对遍历结果进行过滤
start with --start with 必须出现在 where 之后,但是可以是 where and 之间 入下例
s.areaname='大同'
connect by prior
s.parentid=s.aid
-- 测试 5:继续谈递归关键字出现的位置
-- 需求:根据地区名称查找其所在省份
select s.areaname from s_coalarea_test s
where s.arealevel=1 -- 对遍历结果进行过滤
start with --start with 之前不需要加 and
s.areaname='大同'
connect by prior
s.parentid=s.aid
and s.arealevel=1 - --where 的过滤条件
group by s.areaname -- 既然递归查询也是过滤条件 当然可以跟 group by
order by s.areaname -- 既然递归查询也是过滤条件 当然可以跟 order by
-- 总结:start with ...connect by prior 递归查询也是对结果过滤,类似 where 过滤,先于 where 过滤执行
-- 相信大家理解了吧
-- 本人只是针对测试结果,来分析,没有对其原理分析
以上关于 "[关于数据库, 递归查询][递归查询]ORACLE 中使用递归查询 " 的信息由网友上传分享,希望对您有所帮助 ,感谢您对就爱阅读网的支持!
来源: http://www.92to.com/bangong/2017/06-06/22856649.html