Oracle11gr2新增递归WITH语句(一)

11.2中,WITH语句得到进一步的增强,可以支持递归的调用。

这一篇简单介绍WITH语句的递归调用。

 

 

Oracle11.2中增强了WITH语句,使得一些树型查询不再需要CONNECT BY语句就可以完成。

看一个简单的例子:

SQL> SELECT * FROM V$VERSION;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

SQL> CREATE TABLE T_TREE (
  2  ID NUMBER PRIMARY KEY,
  3  FATHER_ID NUMBER,
  4  NAME VARCHAR2(30));

表已创建。

SQL> INSERT INTO T_TREE VALUES (1, 0, 'A');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (2, 1, 'BC');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (3, 1, 'DE');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (4, 1, 'FG');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (5, 2, 'HIJ');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (6, 4, 'KLM');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (7, 6, 'NOPQ');

已创建 1 行。

SQL> INSERT INTO T_TREE VALUES (8, 5, 'RSTU');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM T_TREE;

        ID  FATHER_ID NAME
---------- ---------- ------------------------------
         1          0 A
         2          1 BC
         3          1 DE
         4          1 FG
         5          2 HIJ
         6          4 KLM
         7          6 NOPQ
         8          5 RSTU

已选择8行。

看一个树型查询的例子:

SQL> SELECT *
  2  FROM T_TREE
  3  START WITH ID = 2
  4  CONNECT BY PRIOR ID = FATHER_ID;

        ID  FATHER_ID NAME
---------- ---------- ------------------------------
         2          1 BC
         5          2 HIJ
         8          5 RSTU

利用递归的WITH语句,可以实现同样的功能:

SQL> WITH A (ID, FATHER_ID, NAME) AS
  2  (SELECT ID, FATHER_ID, NAME
  3  FROM T_TREE
  4  WHERE ID = 2
  5  UNION ALL
  6  SELECT B.ID, B.FATHER_ID, B.NAME
  7  FROM A, T_TREE B
  8  WHERE A.ID = B.FATHER_ID)
  9  SELECT * FROM A;

        ID  FATHER_ID NAME
---------- ---------- ------------------------------
         2          1 BC
         5          2 HIJ
         8          5 RSTU

这种写法与树型查询相比显得更加清晰易懂。

检查二者的执行计划:

SQL> SET AUTOT ON EXP
SQL> WITH A (ID, FATHER_ID, NAME) AS
  2  (SELECT ID, FATHER_ID, NAME
  3  FROM T_TREE
  4  WHERE ID = 2
  5  UNION ALL
  6  SELECT B.ID, B.FATHER_ID, B.NAME
  7  FROM A, T_TREE B
  8  WHERE A.ID = B.FATHER_ID)
  9  SELECT * FROM A;

        ID  FATHER_ID NAME
---------- ---------- ------------------------------
         2          1 BC
         5          2 HIJ
         8          5 RSTU


执行计划
----------------------------------------------------------
Plan hash value: 374960264

--------------------------------------------------------------------------------------------
|Id|Operation                                 |Name        |Rows|Bytes|Cost (%CPU)|Time    |
--------------------------------------------------------------------------------------------
| 0|SELECT STATEMENT                          |            |   2|   86|    7  (15)|00:00:01|
| 1| VIEW                                     |            |   2|   86|    7  (15)|00:00:01|
| 2|  UNION ALL (RECURSIVE WITH) BREADTH FIRST|            |    |     |           |        |
| 3|   TABLE ACCESS BY INDEX ROWID            |T_TREE      |   1|   43|    1   (0)|00:00:01|
|*4|    INDEX UNIQUE SCAN                     |SYS_C0011143|   1|     |    1   (0)|00:00:01|
|*5|   HASH JOIN                              |            |   1|   56|    6  (17)|00:00:01|
| 6|    RECURSIVE WITH PUMP                   |            |    |     |           |        |
| 7|    TABLE ACCESS FULL                     |T_TREE      |   8|  344|    4   (0)|00:00:01|
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("ID"=2)
   5 - access("A"."ID"="B"."FATHER_ID")

Note
-----
   - dynamic sampling used for this statement (level=2)

SQL> SELECT *
  2  FROM T_TREE
  3  START WITH ID = 2
  4  CONNECT BY PRIOR ID = FATHER_ID;

        ID  FATHER_ID NAME
---------- ---------- ------------------------------
         2          1 BC
         5          2 HIJ
         8          5 RSTU


执行计划
----------------------------------------------------------
Plan hash value: 856284266

-------------------------------------------------------------------------------------------
| Id | Operation                               |Name  |Rows| Bytes |Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|  0 | SELECT STATEMENT                        |      |   8|   344 |    5  (20)| 00:00:01 |
|* 1 |  CONNECT BY NO FILTERING WITH START-WITH|      |    |       |           |          |
|  2 |   TABLE ACCESS FULL                     |T_TREE|   8|   344 |    4   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T_TREE"."FATHER_ID"=PRIOR "T_TREE"."ID")
       filter("ID"=2)

Note
-----
   - dynamic sampling used for this statement (level=2)

可以看到,虽然实现了相同的功能,但是两种方法的执行计划相去甚远,置于哪种方式效率更高,可能需要具体的测试才能确定。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-625297/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/4227/viewspace-625297/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值