oracle 递归用法,oracle递归用法

--测试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

--测试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

递归变形:

1.START WITH 可以省略

比如:SELECT son FROM tree

CONNECT BY PRIOR son = father;

此时不指定树的根的话,就默认把Tree整个表中的数据从头到尾遍历一次,每一个数据做一次根,然后遍历树中其他节点信息.

在这个例子中,上面的sql等价于

SELECT son FROM tree

START WITH father IN (爷爷,爸爸,儿子,孙子NB,孙子SB)

CONNECT BY PRIOR son = father;

那查询到的结果如下,有很多重复信息的

爸爸,孙子SB 儿子,孙子SB 孙子NB,孙子SB

5.还可以加where条件

我上面说了可以把start with,connect 假装看成where 条件一样.所以在这个sql语句其他地方还可以加其他where 语句,可以看成与递归查询无关.只是对整个结果起过滤作用

比如

SELECT son FROM tree WHERE son = '孙子SB'

START WITH father = '爷爷'

CONNECT BY PRIOR son = father;

当然你不能在最后部分加where,不能在connect by最后面再加.

CONNECT_BY_ISCYCLE

我们的树状属性一般都是在一条记录中记录一个当前节点的ID和这个节点的父ID来实现。但是,一旦数据中出现了循环记录,如两个节点互为对方父节点,系统就会报ORA-01436错误:

insert into t_tonedirlib(dirindex,fatherindex,dirname,status) values (666,667,'123',5);

1 row inserted

insert into t_tonedirlib(dirindex,status) values (667,666,'456',5);

1 row inserted

select dirindex,RPAD(' ',2*(LEVEL-1)) || dirname from t_tonedirlib

start with fatherindex = 666

connect by fatherindex = prior dirindex

ORA-01436: 用户数据中的 CONNECT BY 循环

10G中,可以通过加上NOCYCLE关键字避免报错。并且通过CONNECT_BY_ISCYCLE属性就知道哪些节点产生了循环:

select CONNECT_BY_ISCYCLE,dirindex,2*(LEVEL-1)) || dirname

from t_tonedirlib

start with fatherindex = 666

connect by NOCYCLE fatherindex = prior dirindex

CONNECT_BY_ISCYCLE DIRINDEX FATHERINDEX RPAD(' ',2*(LEVEL-1))||dirname

----------------- ---------------- ---------------------------------

0 667 666 456

1 666 667 123

2 rows selected

以上就是在10G中增强的CONNECT BY了。当然对于这些增强特性的作用肯定不止如上介绍的,还需要更多高人去挖掘了。

递归查询例子:

例子:

select s.id,s.PID,s.NAME,s.CATLEVEL from T_CATALOG s

where s.catlevel=3 --对遍历结果进行过滤

start with --start with 必须出现在where之后,但是可以是where and之间 入下例

s.id=27701

connect by prior

s.id=s.pid

关联商品

SELECT * FROM (

SELECT s.id,s.CATLEVEL from T_CATALOG s

where s.catlevel=3 --对遍历结果进行过滤

start with --start with 必须出现在where之后,但是可以是where and之间 入下例

s.id=27701

connect by prior

s.id=s.pid) cat

JOIN T_PRODUCT p ON p.CATALOGID=cat.ID

如果直接join,需要用left join

SELECT p.NAME,s.id,s.CATLEVEL from T_CATALOG s

left JOIN T_PRODUCT p ON p.CATALOGID=s.ID

where s.catlevel=3 AND p.NAME IS NOT null --对遍历结果进行过滤

start with --start with 必须出现在where之后,但是可以是where and之间 入下例

s.id=27701

connect by prior

s.id=s.pid

外面join查数量:

SELECT cat.id,cat.name,count(p.ID) count FROM (

SELECT s.id,s.CATLEVEL from T_CATALOG s

where s.catlevel=3 --对遍历结果进行过滤

start with --start with 必须出现在where之后,但是可以是where and之间 入下例

s.id=27701

connect by prior

s.id=s.pid) cat

JOIN T_PRODUCT p ON p.CATALOGID=cat.ID

GROUP by cat.id,cat.name

查询父集合:

--测试4:谈级联条件 --需求:根据地区名,查询上级地区 select s.areaname from s_coalarea_test s start with s.areaname='大同' connect by prior s.parentid=s.aid --注意,此时仅仅是级联条件顺序改变了 --总结:到底是查父节点还是子节点,有级联顺序决定 --规律:【本记录字段】=【连接字段】 --如本实例:是通过本记录的parentid匹配其他记录的aid(主键)结果是查父节点 -- 如顺序颠倒,则是:有本记录的aid(主键)匹配其他记录的parentid,结果是查子节点 select s.id,s.CATLEVEL from T_CATALOG s where s.catlevel=1 --对遍历结果进行过滤 start with --start with 必须出现在where之后,但是可以是where and之间 入下例 s.id=27703 connect by prior s.pid=s.id

总结

以上是编程之家为你收集整理的oracle递归用法全部内容,希望文章能够帮你解决oracle递归用法所遇到的程序开发问题。

如果觉得编程之家网站内容还不错,欢迎将编程之家网站推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle归查询是指在一个表中,某一行的值关联到该表中的另一行,而这个关联是可以归进行的。Oracle提供了几种归查询的方法,包括使用CONNECT BY、WITH RECURSIVE以及PL/SQL等。下面分别介绍一下这几种方法的使用。 1. 使用CONNECT BY进行归查询 CONNECT BY是Oracle提供的一种归查询方法,可以用于查询树形结构、层次结构等具有层级关系的数据。其基本语法如下: ``` SELECT column1, column2, ... FROM table_name START WITH condition CONNECT BY [NOCYCLE] PRIOR column1 = column2; ``` 其中,START WITH是起始条件,CONNECT BY是归条件,NOCYCLE是可选的,用于避免出现环路。PRIOR是关键字,表示归的上一级。 举个例子,假设我们有一个表emp,其中包含员工编号、员工姓名、直接上级编号等字段。我们可以使用如下语句查询某个员工的所有下属: ``` SELECT emp_name FROM emp START WITH emp_id = 1 CONNECT BY PRIOR emp_id = mgr_id; ``` 这段代码的意思是,找到emp_id为1的员工,然后归查询该员工的所有下属,直到没有下属为止。 2. 使用WITH RECURSIVE进行归查询 WITH RECURSIVE是SQL标准中定义的一种归查询方法,可以用于查询树形结构、层次结构等具有层级关系的数据。其基本语法如下: ``` WITH RECURSIVE cte_name(column1, column2, ...) AS ( SELECT column1, column2, ... FROM table_name WHERE condition UNION ALL SELECT column1, column2, ... FROM table_name, cte_name WHERE condition ) SELECT column1, column2, ... FROM cte_name; ``` 其中,cte_name是WITH子句中归查询的名称,column1、column2等是需要查询的字段,table_name是要查询的表名,condition是查询条件。 举个例子,我们可以使用如下语句查询某个员工的所有下属: ``` WITH RECURSIVE cte(emp_id, emp_name, mgr_id) AS ( SELECT emp_id, emp_name, mgr_id FROM emp WHERE emp_id = 1 UNION ALL SELECT emp.emp_id, emp.emp_name, emp.mgr_id FROM emp, cte WHERE emp.mgr_id = cte.emp_id ) SELECT emp_name FROM cte; ``` 这段代码的意思是,先找到emp_id为1的员工,然后归查询该员工的所有下属,直到没有下属为止。 3. 使用PL/SQL进行归查询 在PL/SQL中,我们可以使用循环或归函数进行归查询。举个例子,我们可以使用如下函数查询某个员工的所有下属: ``` CREATE OR REPLACE FUNCTION get_subordinates(p_emp_id NUMBER) RETURN SYS_REFCURSOR IS v_cursor SYS_REFCURSOR; BEGIN OPEN v_cursor FOR SELECT emp_name FROM emp WHERE mgr_id = p_emp_id; FOR emp IN v_cursor LOOP dbms_output.put_line(emp.emp_name); get_subordinates(emp.emp_id); END LOOP; RETURN v_cursor; END; ``` 这段代码的意思是,先查询mgr_id为指定员工编号的员工,然后逐个输出其下属的名字,并归调用自身查询下属的下属,直到没有下属为止。 以上是Oracle归查询的几种方法,不同的方法适用于不同的情况。开发者可以根据实际需求选择最合适的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值