zoukankan      html  css  js  c++  java
  • 转:Oracle中CONNECT BY LOOP的使用.非常不错

    CONNECT BY LOOP

    A loop in user data generates an �ORA-01436: CONNECT BY loop in user data� error. A loop is defined in the Oracle Database SQL Language Reference (11.1) documentation as:

    A loop occurs if one row is both the parent (or grandparent or direct ancestor) and a child (or a grandchild or a direct descendent) of another row

    WITH
       T
    AS
    (
       SELECT
          'JOHN' EMPLOYEE,
          'JACK' MANAGER
       FROM
          DUAL
       UNION ALL
       SELECT
          'JACK' EMPLOYEE,
          'JOHN' MANAGER
       FROM
          DUAL
    )
    SELECT
       EMPLOYEE,
       MANAGER
    FROM
       T
    CONNECT BY
       PRIOR EMPLOYEE = MANAGER; 

    ERROR:
    ORA-01436: CONNECT BY loop in user data

    There is a loop in the user data because John is both the manager and the employee of Jack.

    CONNECT BY NOCYCLE and CONNECT_BY_ISCYCLE

    With the 10g keyword NOCYCLE, hierarchical queries detect loops and do not generate errors. CONNECT_BY_ISCYCLEpseudo-column is a flag that can be used to detect which row is cycling.

    WITH
       T
    AS
    (
       SELECT
          'JOHN' EMPLOYEE,
          'JACK' MANAGER
       FROM
          DUAL
       UNION ALL
       SELECT
          'JACK' EMPLOYEE,
          'JOHN' MANAGER
       FROM
          DUAL
    )
    SELECT
       SYS_CONNECT_BY_PATH (EMPLOYEE,'/') as EMPLOYEE,
       MANAGER,
       CONNECT_BY_ISCYCLE
    FROM
       T
    CONNECT BY
    NOCYCLE
       PRIOR EMPLOYEE = MANAGER;
     

    EMPLOYEE       MANAGER CONNECT_BY_ISCYCLE
    -------------- ------- ------------------
    /JOHN          JACK                     0
    /JOHN/JACK     JOHN                     1
    /JACK          JOHN                     0
    /JACK/JOHN     JACK                     1

    Sub-employee Jack is cycling because he is the child and parent of John. John is also cycling, because he is the child and parent of Jack.

    CONNECT BY without PRIOR

    A very popular usage of hierarchical query, documented by Vadim Tropashko in his book SQL Design Patterns, is to generate rows.

    SELECT
       SYS_CONNECT_BY_PATH(DUMMY, '/')
    FROM
       DUAL
    CONNECT BY
       LEVEL<4;

    SYS_CONNECT_BY_PATH(DUMMY,'/')
    --------------------------------
    /X
    /X/X
    /X/X/X
     

    NOTE:  According to the official documentation, PRIOR is mandatory.
    Oracle Database SQL Language Reference (11.1)
    In a hierarchical query, one expression in the CONNECT BY condition must be qualified by the PRIOR operator�. 

    The single row of dual is both the parent and the child of itself but no loop is generated. It is a very efficient way to generate rows.

    CONNECT_BY_IS_LEAF

    The 10g pseudo-column CONNECT_BY_IS_LEAFidentifies rows that do not have descendants.

    SELECT
       SYS_CONNECT_BY_PATH(ENAME, '/')
    FROM
       EMP
    WHERE
       CONNECT_BY_IS_LEAF=1
    START WITH
       MGR IS NULL
    CONNECT BY
       PRIOR EMPNO=MGR;

    SYS_CONNECT_BY_PATH(ENAME,'/')
    -----------------------------------
    /KING/JONES/SCOTT/ADAMS
    /KING/JONES/FORD/SMITH
    /KING/BLAKE/ALLEN
    /KING/BLAKE/WARD
    /KING/BLAKE/MARTIN
    /KING/BLAKE/TURNER
    /KING/BLAKE/JAMES
    /KING/CLARK/MILLER

    Only complete paths from the ancestor where MGR is null to the last descendants are displayed.

    WHERE and JOIN

    Oracle detects in the where clause if the condition is a join condition or a not-join condition. There is a big difference between a join and a not-join condition in that the former is performed before the building of the hierarchy and the later is performed after the hierarchy.

    SELECT
       SYS_CONNECT_BY_PATH(EMP.ENAME, '/') P
    FROM
       EMP,
       TABLE
       (
          SYS.ODCINUMBERLIST(20, 30)
       ) T
    WHERE
       EMP.DEPTNO=T.COLUMN_VALUE
    CONNECT BY
       PRIOR EMP.EMPNO=EMP.MGR
    START WITH
       MGR IS NULL;

    no rows selected

    Oracle detects the join and selects the matching rows. 

    Only rows from the departments 20 and 30 are used to build the hierarchy. No row in the departments 20 and 30 satisfies the condition MGR IS NULL.

    SELECT
       SYS_CONNECT_BY_PATH(EMP.ENAME, '/') P
    FROM
       EMP 
    WHERE
       EMP.DEPTNO IN (20, 30)
    CONNECT BY
       PRIOR EMPNO=MGR
    START WITH
       MGR IS NULL;

    P
    ---------------------------
    /KING/JONES
    /KING/JONES/SCOTT
    /KING/JONES/SCOTT/ADAMS
    /KING/JONES/FORD
    /KING/JONES/FORD/SMITH
    /KING/BLAKE
    /KING/BLAKE/ALLEN
    /KING/BLAKE/WARD
    /KING/BLAKE/MARTIN
    /KING/BLAKE/TURNER
    /KING/BLAKE/JAMES

    The condition is not a join; therefore, the hierarchy is built with all rows. Later, the condition is applied to the children.

    SELECT
       P
    FROM
       (
          SELECT
             SYS_CONNECT_BY_PATH(EMP.ENAME, '/') P,
             DEPTNO
          FROM
             EMP 
          CONNECT BY
             PRIOR EMPNO=MGR
          START WITH
             MGR IS NULL
       )
    WHERE
       DEPTNO IN (20, 30);

    P
    ---------------------------
    /KING/JONES
    /KING/JONES/SCOTT
    /KING/JONES/SCOTT/ADAMS
    /KING/JONES/FORD
    /KING/JONES/FORD/SMITH
    /KING/BLAKE
    /KING/BLAKE/ALLEN
    /KING/BLAKE/WARD
    /KING/BLAKE/MARTIN
    /KING/BLAKE/TURNER
    /KING/BLAKE/JAMES

    The same query again appears with a subquery. This time, the hierarchy is built with all rows in the subquery and the condition applies to the main query.

    The JOINsyntax allows more flexibility to define what should be processed before the hierarchy and what should be processed after.

    SELECT
       SYS_CONNECT_BY_PATH(ENAME, '/') P
    FROM
       EMP
    JOIN
       DUAL
    ON
    (
       HIREDATE > DATE '1981-06-01'
    )
    WHERE
       JOB='CLERK'
    CONNECT BY
       PRIOR EMPNO=MGR
    START WITH
       MGR IS NULL; 

    P
    --------------------
    /KING/CLARK/MILLER

    The DUAL table is joined to EMP. The ON clause is defined before computing the hierarchy, so the whole tree will contain only employees hired after June 1, 1981. The WHERE clause returns only the clerks. The path from the president to the clerks exclusively contains new employees. 

    魔兽就是毒瘤,大家千万不要玩。
  • 相关阅读:
    编程能力的四种境界
    《javascript高级程序设计》笔记五(转载)
    js学习总结----数据类型检测的四种方式(转载)
    初识数据库
    从你家的衣柜,理解软件编程的「架构」
    前端项目工程化 -- 自动化构建初体验
    ECMAScript -- let 和块级作用域
    异步编程 -- 手写Promise初体验
    前端项目工程化 -- webpack -- Source Maps
    异步编程 -- Promise
  • 原文地址:https://www.cnblogs.com/tracy/p/1722247.html
Copyright © 2011-2022 走看看