当对象存在父节点、子节点时,通过特定的方式获取父节点、子节点数据构建树状结构或其它形式结构时,通常都会使用递归,如:一个公司有多个部门、每个部门下可能有多个小部门,小部门下面又有组….为了数据容易管理和维护,通过构建合适的表结构存储这些数据,以下示例以省市县为例学习了解递归:
1.创建存储省市县数据表:

   1:  create table tb_distree
   2:  (
   3:  id number,
   4:  name varchar2(300),
   5:  pid number
   6:  )
   7:  /
   8:   remark 添加主外键
   9:  alter table tb_distree add (
  10:  constraints pk_id primary key(id),
  11:  constraints fk_pid foreign key(pid) references tb_distree(id)
  12:  )
  13:  /

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

2.初始化数据:

   1:  insert into tb_distree(id,name) values(1,'云南省');
   2:  insert into tb_distree(id,name,pid) values(2,'昆明市',1);
   3:  insert into tb_distree(id,name,pid) values(3,'临沧市',1);
   4:  insert into tb_distree(id,name,pid) values(4,'丽江市',1);
   5:  insert into tb_distree(id,name,pid) values(5,'云县',3);
   6:  insert into tb_distree(id,name,pid) values(6,'凤庆',3);
   7:  insert into tb_distree(id,name,pid) values(7,'幸福',3);
   8:  insert into tb_distree(id,name,pid) values(8,'盘龙区',2);
   9:  insert into tb_distree(id,name,pid) values(9,'五华区',2);
  10:  insert into tb_distree(id,name,pid) values(10,'西山区',2);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

3.递归查询语法:

   1:  select column... from table_name 
   2:  where ....  过滤条件
   3:  start with ...  递归开始点
   4:  connect by prior .... 优先级

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

4.递归查询数据:

4.1 从父节点开始查询出所有父节点和子节点:

SQL> select id,name,pid from tb_distree start with pid is null connect by prior id=pid;
 
        ID NAME                PID
---------- ------------ ----------
         1 云南省
         2 昆明市                1
         8 盘龙区                2
         9 五华区                2
        10 西山区                2
         3 临沧市                1
         5 云县                  3
         6 凤庆                  3
         7 幸福                  3
         4 丽江市                1
 
10 rows selected.

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

4.2 查询某个节点的父节点:

 SQL> select id,name,pid from tb_distree start with name='云县' connect by prior pid=id;
 
        ID NAME                PID
---------- ------------ ----------
         5 云县                  3
         3 临沧市                1
         1 云南省

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

在上例中"云县"属于"临沧市","临沧市"属于"云南省";对于从父节点递归到子节点,优先级条件为子节点id等于父节点id;对于从子节点到父节点递归,方向刚好相反;

4.3 通过层次查询出父节点和某个子节点:

SQL> select id,name,pid,level from tb_distree where level in(1,2) start with pid is null connect by prior id=pid;
 
        ID NAME                PID      LEVEL
---------- ------------ ---------- ----------
         1 云南省                           1
         2 昆明市                1          2
         3 临沧市                1          2
         4 丽江市                1          2

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

层次也很重要,某些时候要修改某个节点父节点或子节点时会很有用;

5. 递归查询效率:    

SQL>select/*+ selectDG1 */ id,name,pid from tb_distree start with pid is null connect by prior id=pid;
 
SQL> select sql_id,sql_text from v$sql where sql_text like '%selectDG1%' ;    
SQL_ID          SQL_TEXT
--------------- --------------------------------------------------
2wnu324ga4n0y   select sql_id,sql_text from v$sql where sql_text l
                ike '%selectDG1%'
 
d4g89bucsbvzd   select/*+ selectDG1 */ id,name,pid from tb_distree
                 start with pid is null connect by prior id=pid
 
         
SQL>select * from table(dbms_xplan.display_cursor('d4g89bucsbvzd',null,'advanced allstats last peeked_binds'));
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------
SQL_ID  d4g89bucsbvzd, child number 0
-------------------------------------
select/*+ selectDG1 */ id,name,pid from tb_distree start with pid is
null connect by prior id=pid
 
Plan hash value: 1466399788
 
------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name       | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |            |      1 |        |       |    18 (100)|          |     10 |00:00:00.01 |      22 |
 
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------
|*  1 |  CONNECT BY NO FILTERING WITH START-WITH|            |      1 |        |       |            |          |     10 |00:00:00.01 |      22 |
|   2 |   TABLE ACCESS FULL                     | TB_DISTREE |      1 |     10 |  1780 |    17   (0)| 00:00:01 |     10 |00:00:00.01 |      22 |
------------------------------------------------------------------------------------------------------------------------------------------------
 
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
 
   1 - SEL$1
   2 - SEL$2 / TB_DISTREE@SEL$2
 
Outline Data
 
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------
  /*+
      BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      DB_VERSION('11.2.0.3')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$2")
      OUTLINE_LEAF(@"SEL$3")
      OUTLINE_LEAF(@"SEL$4")
 
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------------------
      OUTLINE_LEAF(@"SET$1")
      OUTLINE_LEAF(@"SEL$1")
      NO_ACCESS(@"SEL$1" "connect$_by$_work$_set$_006"@"SEL$1")
      NO_CONNECT_BY_FILTERING(@"SEL$1")
      CONNECT_BY_COMBINE_SW(@"SEL$1")
      FULL(@"SEL$4" "TB_DISTREE"@"SEL$4")
      FULL(@"SEL$3" "connect$_by$_pump$_002"@"SEL$3")
      FULL(@"SEL$3" "TB_DISTREE"@"SEL$3")
      LEADING(@"SEL$3" "connect$_by$_pump$_002"@"SEL$3" "TB_DISTREE"@"SEL$3")
      USE_HASH(@"SEL$3" "TB_DISTREE"@"SEL$3")
      FULL(@"SEL$2" "TB_DISTREE"@"SEL$2")
 
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------
      END_OUTLINE_DATA
  */
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - access("PID"=PRIOR NULL)
       filter("PID" IS NULL)
       
 10046 trace:
Rows (1st) Rows (avg) Rows (max)  Row Source Operation
 675 ---------- ---------- ----------  ---------------------------------------------------
 676         10         10         10  CONNECT BY NO FILTERING WITH START-WITH (cr=22 pr=0 pw=0 time=269 us)
 677         10         10         10   TABLE ACCESS FULL TB_DISTREE (cr=22 pr=0 pw=0 time=118 us cost=17 size=1780 card=10)
 678 
 679 
 680 Elapsed times include waiting on following events:
 681   Event waited on                             Times   Max. Wait  Total Waited
 682   ----------------------------------------   Waited  ----------  ------------
 683   row cache lock                                  3        0.00          0.00
 684   Disk file operations I/O                        1        0.00          0.00
 685   db file sequential read                         3        0.03          0.04
 686   SQL*Net message to client                       2        0.00          0.00
 687   SQL*Net message from client                     2        0.00          0.00                                                                                                      
 688 ********************************************************************************              

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

在递归表上创建索引是没有用的,都必须进行全表扫描,当然通常这样的表也不会很大,如果数据量的确很大,建议将表中的节点拆分成多个表提高效率;

Oracle 递归的更多相关文章

  1. Oracle 递归的写法(start with) 以及where条件作用域

    先转一个讲Oracle递归讲得非常透彻的文章: http://blog.csdn.net/weiwenhp/article/details/8218091 前言:嗯,这也是一个前人挖坑,后人来填的故事 ...

  2. oracle 递归应用(挺复杂的)

    最近做数据过滤觉得很有必要记录下整个过程,说不定下次就不知道了. 废话不多说开始: 表结构: 企业表(自关联,采用树的形式记录分子公司) 区域表(自关联,采用树的形式记录省/市/县/乡,数据量大) 公 ...

  3. oracle 递归和connect by【转】

    oracle递归查询(单表包含多级上下级关系) http://www.cnblogs.com/walk-the-Line/p/4882866.html -- 查找所有第一层(包括)下的所有子节点 -- ...

  4. oracle递归层级查询 start with connect by prior

    递归层级查询:start with connect by prior  以部门表作为解析 表结构:dept{id:'主键',name:'部门名称',parent_id:'父亲id'} select * ...

  5. Oracle递归sql笔记

    查询一个机构下所辖机构: select * from t00_organ t start with t.organkey=#uporgankey# connect by prior t.organke ...

  6. Oracle递归 start with...connect by...prior

    prior一侧是父节点 另一侧是子节点 --查询region_id等于4519的节点下面的所有子节点 查找出给定节点的所有子节点 SELECT sr.* FROM spc_region sr wher ...

  7. Oracle递归操作

    需求:找出代理商中没有挂商家的代理商 简单SQL如下: select * from t_proxy tp where tp.id not in (SELECT tp.id as p_id FROM t ...

  8. [oracle] 递归追溯完整部门名称 函数

    create or replace function fn_DeptWholeName2(objectid in number) return nvarchar2 is wholename nvarc ...

  9. oracle 分页(rownum的理解) 以及 树节点的查询

    1:什么是rownum, rownum的生成, rownum相关的符号操作 Rownum是oracle生成结果集时得到的一个伪列, 按照读出行的顺序, 第一条rownum=1, 第二条=2. 对于 O ...

随机推荐

  1. 第六章 hbase shell 命令

    hbase shell命令                             描述  alter 修改列族(Column Family)模式 count 统计表中行的数量 create 创建表 ...

  2. C++:const_cast类型转换

    针对const_cast,太多人在用同一个示例问同一个问题:void main(){   const int a = 3;   const int *pc = &a;   int *p = c ...

  3. [置顶] C语言中 || 和 &&

    || 或操作,|| 为界将表达式分为两部分,他会先算前一部分,如果前一部分为真,他将停止运算,如果为假,他才会算第二部分,你这里第一部分就为真了,第二部分当然也就不会算了. 例如:  a || b , ...

  4. json-lib使用笔记

    今天再来记录一款生成JSON的工具——json-lib,它比较与我之前使用的FastJSON来说,使用都是很简单的,但是要使用json-lib要需要的jar包可真不少,所需要的依赖jar有八九个之多, ...

  5. Clustering Factor——索引的成本指标

    使用索引是我们面对海量数据搜索是一种常用的手段.通过有效的索引访问,可以使我们更快的访问到需要的数据,减少物理.逻辑IO,从而提高系统性能.在CBO时代,Oracle对于提交SQL的执行路径是有所选择 ...

  6. sed、grep、awk -- 三剑客笔记记录

    sed常用操作笔记   1.删除文件最后一行: sed -i '$d' filename 2.递归替换内容:sed -i 's/内容A/内容B/g' filename sed -i "s/S ...

  7. angularJS开发碰到的问题

    bootstarp css无法加载 http://stackoverflow.com/questions/27656503/how-to-make-yo-angular-load-bootstrap- ...

  8. 用 Sqlmap 识别 WAF

    命令: ┌─[root@sch01ar]─[~] └──╼ #sqlmap -u "http://www.sch01ar.com/" --identify-waf --batch ...

  9. SpringBoot+rest接口+swagger2生成API文档+validator+mybatis+aop+国际化

    代码地址:JillWen_SpringBootDemo mybatis 1. 添加依赖: <dependency> <groupId>org.mybatis.spring.bo ...

  10. mac下mysql5.7.18修改root密码

    参考:http://blog.csdn.net/lijilong_/article/details/70991809 第一步:苹果->系统偏好设置->最下面点MySQL,关闭mysql服务 ...