例如有表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限制相关推荐

  1. mysql start with connect by_MYSQL实现Oracle的Start with…Connect By递归树查询

    最近接触一个老项目,最初适配的数据库是oracle 后来迁移到mysql .这个迁移是由一个已经离职的新手做的.这个新手对于很多oracle特有的函数及存储过程都没有进行迁移.导致系统很多功能都BUG ...

  2. 【数据库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 客户端:命令行 ...

  3. [20180602]函数与标量子查询3.txt

    [20180602]函数与标量子查询3.txt --//前面看http://www.cnblogs.com/kerrycode/p/9099507.html链接,里面提到: 通俗来将,当使用标量子查询 ...

  4. 20180601]函数与标量子查询2.txt

    [20180601]函数与标量子查询2.txt --//昨天看http://www.cnblogs.com/kerrycode/p/9099507.html链接,里面提到: 通俗来将,当使用标量子查询 ...

  5. mysql递归层次查询

    mysql递归层次查询 最近在做一个从oracle数据库到mysql数据库的移植,遇到一个这样的问题 在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT B ...

  6. mysql用户变量递归_MYSQL递归树查询的实现

    ​    在oracle中我们可以使用connect by prior 函数来实现组织树表递归的查询,但是在mysql中却没有该方法,为了能够使用该方法我们就得自己创建函数来实现该组织树的递归查询.以 ...

  7. mysql 单标递归_MYSQL递归树查询的实现

    ​    在oracle中我们可以使用connect by prior 函数来实现组织树表递归的查询,但是在mysql中却没有该方法,为了能够使用该方法我们就得自己创建函数来实现该组织树的递归查询.以 ...

  8. 金仓数据库 KingbaseES SQL 语言参考手册 (10. 查询和子查询)

    10. 查询和子查询 本章描述SQL查询以及子查询.包含以下章节: 关于查询和子查询 创建简单查询 层次查询 集合操作 查询结果排序 JOIN操作 使用子查询 限制嵌套查询层数 DUAL表查询 10. ...

  9. 数据库 day60,61 Oracle入门,单行函数,多表查询,子查询,事物处理,约束,rownum分页,视图,序列,索引

    1.    oracle介绍 ORACLE数据库系统是美国ORACLE公司(甲骨文)提供的以分布式数据库为核心的一组软件产品,是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的 ...

最新文章

  1. 人脑是怎么防止梯度消失和梯度爆炸的?
  2. Android之加载外部dex
  3. Xmodem恢复交换机IOS
  4. python的用途实例-三个实例带你了解生成器的作用
  5. GetAsyncKeyState
  6. python源码多平台编译_ubuntu编译python源码的坑
  7. 虚拟机如何装linux6,如何在vmvare中安装redhat linux6虚拟机
  8. 地址解析协议ARP:ARP欺骗
  9. idea项目能放入eclipse_IDEA导入eclipse项目并且部署到tomcat的步骤详解
  10. WPS表格如何快速添加斜线表头
  11. 计算机网络信息安全毕业设计题目,网络信息安全系统毕业设计
  12. HDU6287 口算训练 【两种优化版分解质因数】【二分下标】
  13. 迅雷9 fetch.php,crossea
  14. 我们称字母顺些和逆写都相同的单词或者短语为“回文”,编写一个Java程序判断输入的一行文本是否是回文。
  15. 阿里云服务器ECS与域名的绑定
  16. 解密库尔勒可靠性检测
  17. 报错:java.lang.ClassNotFoundException: Cannot find implementation for解决方法
  18. “一52岁程序员老将”,看完这“208道精品面试题”;最终成功跳槽阿里P8,从此平步青云,飞黄腾达
  19. 图文:微博平台首席架构师杨卫华演讲
  20. 那周余嘉熊掌将得队——用户使用调查报告

热门文章

  1. 搭建阿里云Linux版服务器+使用docker安装EMQ、Node-RED、MySQL+本地Navicat访问数据库(增删改查)——详细流程
  2. 贪心 阿狸和桃子的游戏
  3. hp笔记本win10无法关闭飞行模式
  4. IP协议详解之头部结构
  5. RTX30 系列游戏本与台式机、云服务器显卡 AI 计算力对比
  6. Mov文件格式对mdat和moov的分析
  7. 《码农翻身》总结整理
  8. 捣鼓nsq - 安装和运行
  9. python猴子分桃_猴子分桃 - Ryan in C++ - 博客园
  10. Maya2022安装教程