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

    作为一名开发人员,大多情况下都会认真的做好功能测试,但是却常常忽略了软件开发之后的压力测试,尤其是在面向大量用户同时使用的Web应用系统的开发过程,压力测试往往是不够充分的.近期我在一个求职招聘型的网 ...

  2. 【转】JMeter 通过 JDBC 访问 Oracle 和 MySQL

    JMeter 的手册中描述了如何访问 MySQL,但是没有说明如何访问 Oracle.对于没有 Java 应用开发经验和对 Oracle 不是特别熟悉的朋友,可以参考这篇文章来简单.快速的配置好 JM ...

  3. Java中的强制类型转换

    例如,当程序中需要将 double 型变量的值赋给一个 int 型变量,该如何实现呢? 显然,这种转换是不会自动进行的!因为 int 型的存储范围比 double 型的小.此时就需要通过强制类型转换来 ...

  4. JVM内存管理和问题简要分析学习

      Java中我们基本上不会显式地调用分配内存的函数,分配内存和回收内存都由JVM自动完成了.   所谓物理内存就是我们通常说的RAM(随机存储器),计算机中还有一个存储单元叫做寄存器,用于存储计算单 ...

  5. 浅谈PHP面向对象编程(四、类常量和静态成员)

    4.0 类常量和静态成员 通过上几篇博客我们了解到,类在实例化对象时,该对象中的成员只被当前对象所有.如果希望在类中定义的成员被所有实例共享. 此时可以使用类常量或静态成员来实现,接下来将针对类常量和 ...

  6. Python代码审计中一些需要重点关注的项

    SQL注入: 如果是常规没有进行预编译,或者直接使用原生的进行拼凑,那么在view的时候就需要多去观察了 [PythonSQL预编译]https://www.cnblogs.com/sevck/p/6 ...

  7. C语言学习笔记---好用的函数memcpy与memset

    这个主要用于我个人的学习笔记,便于以后查询,顺便分享给大家. 想必在用C的时候难免会与数组,指针,内存这几样东西打交道,先以数组为例,例如有一个数组int a[5] = {1, 2, 3, 4, 5} ...

  8. pycharm git工具与coding.net结合

    前提:coding.net中的项目是私密项目 问题描述:在使用pycharm自带的git工具clone(或者push)代码时出现 错误如下:Push failed: Failed with error ...

  9. Django的contenttypes应用、缓存相关

    一.django的contenttypes contenttypes 是Django内置的一个应用 , 可以追踪项目中所有app 和 model 的对应关系, 并记录djang_content_typ ...

  10. log4j:WARN No appenders could be found for logger 解决办法

    转自:https://blog.csdn.net/chw0629/article/details/80567936 使用log4j时不起作用,每次执行完出现以下提示: log4j:WARN No ap ...