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

    Eclipse 导入 Gradle project 时总是报错:Can't load library: native-platform.dll. 解决方案: 进入 Windows -> Pref ...

  2. Tkinter学习

    from tkinter import * window = Tk() # 创建一个窗口 window.mainloop() # 消息循环,显示窗口 window.title("窗口标题&q ...

  3. JAVA构造函数在超类与子类定义鲁波总结

    1.子类无构造函数,超类无构造函数,创建的无参数的对象: 编译通过. class A { } class B extends A { } public class Testeeer { public ...

  4. md5加密(4)

    package test1; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; pu ...

  5. SQL Server 全文索引的硬伤

    本文关键字:SQL Server全文索引.CONTAINS.FREETEXT.CONTAINSTABLE.FREETEXTTABLE等谓词. 想象这样一个场景:在DataBase_name.dbo.T ...

  6. Linux的bond模式绑定及模式区别

    [Linux的bond模式配置] 原理: 多块网卡虚拟成一张,实现冗余:多张网卡对外显示一张,具有同一个IP: 工作在网卡是混杂模式的情况下: 对于多物理网卡的 Bond 网卡而言,其中一块物理网卡会 ...

  7. 关于Spring的Quartz的xml配置的例子

    <span style="font-size:16px"></span><h3><span style="font-family ...

  8. leetcode513

    /** * Definition for a binary tree node. * public class TreeNode { * public int val; * public TreeNo ...

  9. 笔记-TCPCLIENT

    ]; private void ReceiveMessage() { try { tcpClient = );//创建TcpClient对象实例 } catch (Exception le) { } ...

  10. <转> win7下破解已安装的VS2008

    http://renfan.blog.51cto.com/3466724/754301 在win7系统下,已安装的VS2008维护界面是不显示序列号输入的,需要按以下步骤进行才能破解 1.点击“卸载/ ...