PLSQL - 递归子查询RSF打破CONNECT BY LOOP限制
例如有表EMP_ROLES存有数据如下图
RNAME表示员工充当的角色名称,当一人身兼多职时,便会以+号串联各个角色
这是一种很聪明的存储方法,但有时我们却又可能需要拆出每个人的所有角色以便匹配,也就是说要以员工+单角色名称的维度来组织数据,如下图
棘手的地方在于RNAME的内容不是固定的:角色的组合有长有短,组合起来的顺序也可能不同,这使得SQL需要做到动态拆分,这让人容易想到使用正则表达式搭配层次查询拆分,比如:
SQL> select regexp_substr('Oracle_Dev_Share', '[^\_]+', 1, level) r2 from dual3 connect by level <= regexp_count('Oracle_Dev_Share', '\_') + 1;R
-------
Oracle
Dev
Share
但如果在这张表上直接这样使用,结果将是一个灾难
PS:结果行数太多,所以这里加一个START WITH rid = 1以便看出问题原因
SQL> select rid, ename, regexp_substr(rname, '[^\+]+', 1, level) rname, level2 from emp_roles3 start with rid = 14 connect by level <= regexp_count(rname, '\+') + 1;RID ENAME RNAME LEVEL
---- ------------ ------ -----1 YUSUF DAD 13 SCOTT GCM 25 TURNER GCM 34 MARTIN MPC 25 TURNER GCM 35 TURNER MPC 25 TURNER GCM 37 rows selected
简单来说,这是一个未指示父子关系的放飞自我的递归,它只对LEVEL进行了一下筛选:首先YUSUF是第一层,然后全表作为他的下一层(LEVEL = 2),进行到这里要求RNAME的+号数量 ≥ 1,从而QINJINGBAO(角色是SON)被淘汰;下面第二层的各行分别来到第三层,依然是全表作为遴选对象,这里要求RNAME的+号数量 ≥ 2,唯有TURNER可以入选;第四层要求RNAME的+号数量 ≥ 3,不存在这样的行,递归结束
可想而知去掉START WITH rid = 1将得到什么
既然自由的递归不行,指示SQL在同一行上递归可以吗?这样也不行,因为这形成了递归循环(CONNECT BY loop)
SQL> select rid,2 ename,3 regexp_substr(rname, '[^\+]+', 1, level) rname4 from emp_roles5 connect by prior rid = rid6 and level <= regexp_count(rname, '\+') + 1;
select rid,ename,regexp_substr(rname, '[^\+]+', 1, level) rnamefrom emp_roles
connect by prior rid = ridand level <= regexp_count(rname, '\+') + 1ORA-01436: 用户数据中的 CONNECT BY 循环
递归子查询RSF是Oracle 11.2引入的新特性,它没有递归循环的限制,用RSF可以较为轻松地解决这个问题
SQL> with rsf_q(rid, ename, rname, lv) as2 (select er.rid, er.ename, regexp_substr(er.rname, '[^\+]+') rname, 1 lv3 from emp_roles er4 union all5 select er.rid,6 er.ename,7 regexp_substr(er.rname, '[^\+]+', 1, rq.lv + 1) rname,8 rq.lv + 1 lv9 from rsf_q rq, emp_roles er10 where rq.rid = er.rid11 and rq.lv <= regexp_count(er.rname, '\+'))12 search depth first by rid set rorder13 select rid, ename, rname from rsf_q;RID ENAME RNAME
---- ------------ ------1 YUSUF DAD2 QINJINGBAO SON3 SCOTT MPC3 SCOTT GCM4 MARTIN GCM4 MARTIN MPC5 TURNER MM5 TURNER MPC5 TURNER GCM9 rows selected
在11.2以前,可以考虑构造虚拟行集来关联实现裂行
SQL> with e_roles as2 (select er.rid, er.ename, er.rname, regexp_count(er.rname, '\+') + 1 rcount3 from emp_roles er),4 pseudo_rows as5 (select level row_num6 from dual7 connect by level <= (select max(rcount) from e_roles))8 select er.rid,9 er.ename,10 regexp_substr(er.rname, '[^\+]+', 1, pr.row_num) rname11 from e_roles er, pseudo_rows pr12 where er.rcount >= pr.row_num13 order by er.rid, er.ename, pr.row_num;RID ENAME RNAME
---- ------------ ------1 YUSUF DAD2 QINJINGBAO SON3 SCOTT MPC3 SCOTT GCM4 MARTIN GCM4 MARTIN MPC5 TURNER MM5 TURNER MPC5 TURNER GCM
PLSQL - 递归子查询RSF打破CONNECT BY LOOP限制相关推荐
- mysql start with connect by_MYSQL实现Oracle的Start with…Connect By递归树查询
最近接触一个老项目,最初适配的数据库是oracle 后来迁移到mysql .这个迁移是由一个已经离职的新手做的.这个新手对于很多oracle特有的函数及存储过程都没有进行迁移.导致系统很多功能都BUG ...
- 【数据库1】mysql,DDL/DML,DQL,外键约束,多表/子查询,事务,登陆,连接池,jdbc,redis,crontab,ftp,oracle,数据交换/存储/收集
文章目录 1.mysql安装:存储:集合(内存:临时),IO流(硬盘:持久化) 1.1 服务端:双击mysql-installer-community-5.6.22.0.msi 1.2 客户端:命令行 ...
- [20180602]函数与标量子查询3.txt
[20180602]函数与标量子查询3.txt --//前面看http://www.cnblogs.com/kerrycode/p/9099507.html链接,里面提到: 通俗来将,当使用标量子查询 ...
- 20180601]函数与标量子查询2.txt
[20180601]函数与标量子查询2.txt --//昨天看http://www.cnblogs.com/kerrycode/p/9099507.html链接,里面提到: 通俗来将,当使用标量子查询 ...
- mysql递归层次查询
mysql递归层次查询 最近在做一个从oracle数据库到mysql数据库的移植,遇到一个这样的问题 在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT B ...
- mysql用户变量递归_MYSQL递归树查询的实现
在oracle中我们可以使用connect by prior 函数来实现组织树表递归的查询,但是在mysql中却没有该方法,为了能够使用该方法我们就得自己创建函数来实现该组织树的递归查询.以 ...
- mysql 单标递归_MYSQL递归树查询的实现
在oracle中我们可以使用connect by prior 函数来实现组织树表递归的查询,但是在mysql中却没有该方法,为了能够使用该方法我们就得自己创建函数来实现该组织树的递归查询.以 ...
- 金仓数据库 KingbaseES SQL 语言参考手册 (10. 查询和子查询)
10. 查询和子查询 本章描述SQL查询以及子查询.包含以下章节: 关于查询和子查询 创建简单查询 层次查询 集合操作 查询结果排序 JOIN操作 使用子查询 限制嵌套查询层数 DUAL表查询 10. ...
- 数据库 day60,61 Oracle入门,单行函数,多表查询,子查询,事物处理,约束,rownum分页,视图,序列,索引
1. oracle介绍 ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的 ...
最新文章
- 人脑是怎么防止梯度消失和梯度爆炸的?
- Android之加载外部dex
- Xmodem恢复交换机IOS
- python的用途实例-三个实例带你了解生成器的作用
- GetAsyncKeyState
- python源码多平台编译_ubuntu编译python源码的坑
- 虚拟机如何装linux6,如何在vmvare中安装redhat linux6虚拟机
- 地址解析协议ARP:ARP欺骗
- idea项目能放入eclipse_IDEA导入eclipse项目并且部署到tomcat的步骤详解
- WPS表格如何快速添加斜线表头
- 计算机网络信息安全毕业设计题目,网络信息安全系统毕业设计
- HDU6287 口算训练 【两种优化版分解质因数】【二分下标】
- 迅雷9 fetch.php,crossea
- 我们称字母顺些和逆写都相同的单词或者短语为“回文”,编写一个Java程序判断输入的一行文本是否是回文。
- 阿里云服务器ECS与域名的绑定
- 解密库尔勒可靠性检测
- 报错:java.lang.ClassNotFoundException: Cannot find implementation for解决方法
- “一52岁程序员老将”,看完这“208道精品面试题”;最终成功跳槽阿里P8,从此平步青云,飞黄腾达
- 图文:微博平台首席架构师杨卫华演讲
- 那周余嘉熊掌将得队——用户使用调查报告