写代码时碰到要弄清楚Oracle的role之间的传递关系,就是有role A的话,可以通过grant A to B,把A赋予给B,又通过grant B to C .那我想知道所有role中,有哪些role具有A的权限.

  上网一查发现有个递归查询,不过都讲的不是太详细,而那Oracle整的那用法实在太怪异了,跟我们平时用的SQL差的太远,所以琢磨了好一阵子脑子才转过弯呢.

树形结构

  可能一看到递归查询这样太专业的名词大家就迷糊了.实际上可以看成有一个树形结构,然后我们要怎么把所有树的所有结点查找出来.学数据结构的时候我们知道要遍历一个树结构有啥前序遍历,中序遍历,后序遍历.反正挺麻烦的.不像遍历个数组那么容易的.那实际上在Oracle的一个表中也可以保存树形结构信息.你要查询所有的树节点,自己整个函数或存储过程去整肯定是超级麻烦的.Oracle提供了一个简单的机制帮助你.要用到start withnnect by等关键字.先来假定有下面这样一个简单的树形结构存储在表中.

  create table Tree(son char(10), father char(10)); 然后插入些信息变成这样的表

  SON            FATHTER

  孙子SB         儿子

  孙子NB         儿子

  儿子            爸爸

  爸爸            爷爷

  很显然这是一个简单的树形结构

  孙子SB

  ^

  |

  爷爷 --> 爸爸 --> 儿子 -->孙子NB

递归查询

  假如要查询出以爷爷为根的树的所有节点值咋整呢 ?如果数据少多来几个where嵌套就行.但要是树层次有几百那会搞死人了啊.于是我们就用Oracle提供的递归查询.先看下SQL的写法然后再讲解

  SELECT  son FROM tree

  START WITH father = '爷爷'

  CONNECT BY PRIOR son = father;

  返回的结果为 爸爸 儿子 孙子NB 孙子SB

  代码看起来很短,但是极为怪异,脑子半天都不容易转过弯呢.实际上我们不把这个SQL语句跟一般的SQL类比,而把它当作给一些函数指定一些参数的赋值语句才更容易理解.

  那怎么来理解上面的SQL呢?

  首先把SELECT son FROM tree还是看成一般sql一样,就是要查找son这一列的信息.而把以START WITH开头的后面所有东东看成一个where限制条件.其中START WITH 是指定

  树的根,这里指定的根是 '爷爷',实际上你还可以指定多个根的,比如 father in ('爷爷', '爸爸') .

  而CONNECT BY PRIOR son = father相当于表明在递归的过程中,查找到的树中其它节点接着又作为根结点.然后继续递归. 反正看这sql语句前先想下树形结构,然后想下一般编程语言中的递归函数.再来看时就容易理解点.实际上我觉得Oracle这样设计不太好.如果用户只是简单的指定的一个根节点然后知道树中其他节点信息.那么就直接用START WITH指定根就行了.CONNECT BY PRIOR显得有点多余,可以不用用户去指定.当作一个默认值,只有需要其他一些更复杂的操作时才让用户明确指定.这样就不容易误导人了.

  为了便于理解可以可以CONNECT BY那一行当作多余的,只记住要查询的列名放前面,根列名放等号后面就行.这样只要指定树的根结点就比较好理解了.

start with ,connect by prior其他变形

  上面讲的用START WITH 指定树的根,然后用CONNECT BY指定递归条件.是最简单的也是最常用的形式.但实际上还有些变形.

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;

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

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

2.START WITH 与CONNECT BY PRIOR位置可互换

  SELECT son FROM tree

  CONNECT BY PRIOR son = father

  START WITH father = '爷爷';

  这语句与最开头那个是等价的

3.nocycle关键字

  我们知道标准的树结构中是不会有环的,但表中的树形结构不是标准的,有可能导致环的出现

  比如

  ---------孙子SB

  |             ^

  |             |

  爷爷 --> 爸爸 --> 儿子 -->孙子NB

  哎在这里想用线条整个箭头出来真他妈麻烦啊.我又有点懒不想用其他画图工具啥的啊.反正假设儿子的儿子是孙子SB ,而孙子SB的儿子是爸爸.这样就形成一个环了.

  当然在Oracle中的role是禁止出现循环的.比如你grant A to B ,grant B to C .再来个grant C to A会出错的.

  假如有个上面的环,在再使用开始的递归查询语言会出错.得用nocycle关键字指定忽略环.

  SELECT son FROM tree

  START WITH father = '爷爷'

  CONNECT BY NOCYCLE PRIOR son = father;

  此时结果是

  爸爸 儿子 孙子NB

  你会注意到由于忽略了环,所以孙子SB的信息也被忽略掉了.

4. connect by prior 后面条件顺序的改变 ( ?)

  SELECT son FROM tree

  START WITH father = '爷爷'

  CONNECT BY PRIOR son = father;

  这是开头的写法,但实际上也可以写成father = son倒过来写.有人说没倒过来是从上到下,从根往下.如果倒过来则是从下到上.哎不过我测试了下发现不是那么回事.结果也有点乱七八糟的.没想明白是啥规律.反正还有待研究啊

  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最后面再加.

转载来源:http://www.educity.cn/shujuku/1595650.html

Oracle递归查询(start with)的更多相关文章

  1. 【转载】Oracle递归查询:使用prior实现树操作【本文出自叶德华博客】

    本文标题:Oracle递归查询:使用prior实现树操作 本文链接:http://yedward.net/?id=41 本文版权归作者所有,欢迎转载,转载请以文字链接的形式注明文章出处. Oracle ...

  2. 【2016-11-7】【坚持学习】【Day22】【Oracle 递归查询】

    直接在oracle 递归查询语句 select * from groups start with id=:DeptId connect by prior superiorid =id 往下找 sele ...

  3. Oracle递归查询start with connect by prior

    一.基本语法 connect by递归查询基本语法是: select 1 from 表格 start with ... connect by prior id = pId start with:表示以 ...

  4. Oracle递归查询,Oracle START WITH……CONNECT BY查询

    Oracle递归查询,Oracle START WITH……CONNECT BY查询,Oracle树查询 ================================ ©Copyright 蕃薯耀 ...

  5. Oracle递归查询与常用分析函数

    最近学习oracle的一些知识,发现自己sql还是很薄弱,需要继续学习,现在总结一下哈. (1)oracle递归查询  start with ... connect by prior ,至于是否向上查 ...

  6. Oracle 递归查询

    现实中我们经常需要用到一些递归查询,下面我们来介绍下ORACLE中递归查询的使用. 首先我们先新建一个表来存储以上信息 create table FAMILY ( person_id INTEGER, ...

  7. SqlServer CTE 递归查询 Oracle递归查询

    在做数据库设计这块,很多时候表的数据模型就是典型的二叉树结构. 于是在查询数据的时候,就涉及到了数据的递归查询. 递归查询分为两种:1.从根节点查询自身以及所有的子节点:2.从子节点查询自身以及所有的 ...

  8. [转]ORACLE递归查询

    转自:http://www.oracle.com/technetwork/cn/articles/hartley-recursive-086819-zhs.html 递归数据库处理,也称为材料清单 或 ...

  9. (转载)令人迷糊的Oracle递归查询(start with)

    转载地址:https://blog.csdn.net/weiwenhp/article/details/8218091 备注:如有侵权,请联系立即删除. 写代码时碰到要弄清楚Oracle的role之间 ...

随机推荐

  1. Android Studio连接真机

    -------------siwuxie95         1.首先创建一个项目:HelloWorld,点击app,出现下拉选项,选择Edit Configurations             ...

  2. MongoDB 自动分片 auto sharding

    MongoDB部署实验系列文章 MongoDB做为NoSQL数据库,最近几年持续升温,越来越多的企业都开始尝试用MongoDB代替原有Database做一些事情.MongoDB也在集群,分片,复制上也 ...

  3. 如果使用mybatis的逆向工程生成的po类及mapper,如果我们想要进行的对数据库的操作在mapper中没有对应的接口函数:比如生成的mapper接口中没有按照姓名及性别混合条件查询。我们的解决办法是:使用逆向工程生成的对应表的Example文件。

    1.使用mybatis逆向工程生成的po类中包含UserExample文件(我的数据库表名为User). 2. 创建UserExample对象,然后对加入条件.对应的测试代码为: /* * 通过姓名和 ...

  4. Linux远程桌面实现(转)

    http://blog.csdn.net/txg703003659/article/details/6619652 先说一下本人的实现环境: 控制端:Ubuntu 11.04 被控制端:CentOS ...

  5. Windows本地Linux虚拟机ping不通的解决办法

    解决办法:启动虚拟机双网卡支持: 网卡1:Host-Only网络 网卡2:NAT网络 设置好以后,可以在Linux主机中ifconfig查看本地Host-Only的网络地址,与电脑中的地址应该是同一网 ...

  6. PhpStorm 合理标注目录让索引和扫描更加地高效

    在项目开发过程中,以下几种情况让 PhpStorm 加重了索引扫描的负担: 1.npm install 之后产生的 node_modules 目录 2.runtime 运行时产生的目录 3.stora ...

  7. DataStage 错误集(持续更新)

    DataStage 错误集(持续更新) DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 D ...

  8. java集成支付宝移动快捷支付时报错java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: IOException : algid parse error, not a sequence

    出错原因是代码中的私钥设置错误,不是填原始的私钥,而是转换为PKCS8格式的私钥(Java格式的) ,改成后就会报创建交易异常了

  9. Linux的系统引导

    启动引导: 1.主机加电自检,加载BIOS信息 2.读取MBR的引导文件[grub lilo] 3.引导linux内核 4.运行第一个进程init pid=1 5.进入相应的运行级别[0-6] 6.运 ...

  10. Redis-3.2.0集群配置(redis cluster)

    版本:redis-3.0.5 redis-3.2.0  redis-3.2.9  redis-4.0.11 参考:http://redis.io/topics/cluster-tutorial. 目录 ...