Oracle 递归

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

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 / [email protected]$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; }

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

时间: 2024-10-07 14:25:10

Oracle 递归的相关文章

ORACLE 递归树型结构统计汇总

区域平台统计报表,省--市--区 汇总,还有各级医院,汇总与列表要在一个列表显示. 用到ORACLE 会话时临时表  GLOBAL TEMPORARY TABLE     ON COMMIT PRESERVE ROWS; 递归树: START WITH P.PARENTORG = 'ROOT'               CONNECT BY PRIOR P.ORGCODE = P.PARENTORG; WITH 连续嵌套 记录一下便于查阅. CREATE OR REPLACE PACKAGE

Oracle递归树

例子下载: http://yunpan.cn/cLY4v5hdQeMY6 (提取码:ae65) 语法: select ... from <TableName>        where <Conditional-1>  //过滤        start with <Conditional-2>  //递归起点        connect by <Conditional-3>;  //连接限定 注意: 1.prior放在子节点端,则表示扫描树是以start

oracle 递归和connect by【转】

oracle递归查询(单表包含多级上下级关系) http://www.cnblogs.com/walk-the-Line/p/4882866.html -- 查找所有第一层(包括)下的所有子节点 select m.*,LEVEL, CONNECT_BY_ROOT(id) from tb_menu m start with m.id = '1' connect by PRIOR m.id = m.parent; oracle connect by用法 http://www.cnblogs.com/

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

create or replace function fn_DeptWholeName2(objectid in number) return nvarchar2 is wholename nvarchar2(500); beginselect to_char(replace(wm_concat(OBJNAME),',','.'))a into wholename from (select * from v_organddept2 ostart with o.objid=objectidconn

基于CentOS7安装部署 Oracle 12c ?

基于CentOS7安装部署 Oracle 12c 简介 Oracle Database,又名Oracle RDBMS,或简称Oracle.是甲骨文公司的一款关系数据库管理系统.是目前最流行的客户/服务器(CLIENT/SERVER)或B/S体系结构的数据库之一.Oracle数据库最新版本为Oracle Database 12c.Oracle数据库12c 引入了一个新的多承租方架构,使用该架构可轻松部署和管理数据库云. 特点 1.完整的数据管理功能: 1)数据的大量性 2)数据的保存的持久性 3)

oracle和mysql的学习

Oracle和mysql的部分语法区别 一.WM_CONCAT对应GROUP_CONCAT; 二. ronum可用limit代替: 三.sys_guid()用uuid()代替 四.add_months(t2.maxTime,-12)用date_add(t2.maxTime,interval -12 month)代替: date_format(date,'%Y-%m-%d')-->oracle中的to_char(); str_to_date(date,'%Y-%m-%d')-->oracle中的

Linux如何查看进程、杀死进程、启动进程等常用命令

1.查进程    ps命令查找与进程相关的PID号:    ps a 显示现行终端机下的所有程序,包括其他用户的程序.    ps -A 显示所有程序.    ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示.    ps -e 此参数的效果和指定"A"参数相同.    ps e 列出程序时,显示每个程序所使用的环境变量.    ps f 用ASCII字符显示树状结构,表达程序间的相互关系.    ps -H 显示树状结构,表示程序间的相互关系.  

Linux进程命令

关键字: linux 查进程.杀进程.起进程1.查进程    ps命令查找与进程相关的PID号:    ps a 显示现行终端机下的所有程序,包括其他用户的程序.    ps -A 显示所有程序.    ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示.    ps -e 此参数的效果和指定"A"参数相同.    ps e 列出程序时,显示每个程序所使用的环境变量.    ps f 用ASCII字符显示树状结构,表达程序间的相互关系.    ps -

Linux 命令——简约汇总

1. 更改档案拥有者 命令 : chown [-cfhvR] [--help] [--version] user[:group] file... 功能 : 更改文件或者文件夹的拥有者 参数格式 :     user : 新的档案拥有者的使用者 IDgroup : 新的档案拥有者的使用者群体(group)         -c : 若该档案拥有者确实已经更改,才显示其更改动作         -f : 若该档案拥有者无法被更改也不要显示错误讯息         -h : 只对于连结(link)进行