随笔-42  评论-12  文章-0  trackbacks-0

最后,我们来看看在ORACLE DATABASE 10G里对于分等级查询功能的增强。

Oracle Database 10g给我们带来了一些新特性。这些新特性包括CONNECT_BY_ROOT操作符,CONNECT_BY_ISCYCLE 和 CONNECT_BY_ISLEAF伪列,以及NOCYCLE关键字。

CONNECT_BY_ROOT操作符可以从根行取数据。举个例子,我们想查询每个用户及他们对应部门的经理名,可以如下考虑:

SELECT level, lname "Employee" ,dept_id,CONNECT_BY_ROOT lname "Top Manager"
FROM employee
START WITH emp_id in
(SELECT emp_id
FROM employee
START WITH manager_emp_id IS NULL
CONNECT BY manager_emp_id = PRIOR emp_id
AND dept_id != PRIOR dept_id)
CONNECT BY PRIOR emp_id = manager_emp_id
AND dept_id = PRIOR dept_id;

LEVEL                  Employee             DEPT_ID                Top Manager         
---------------------- -------------------- ---------------------- --------------------
1                      JONES                20                     JONES               
2                      SCOTT                20                     JONES               
3                      ADAMS                20                     JONES               
2                      FORD                 20                     JONES               
3                      SMITH                20                     JONES               
1                      BLAKE                30                     BLAKE               
2                      ALLEN                30                     BLAKE               
2                      WARD                 30                     BLAKE               
2                      MARTIN               30                     BLAKE               
2                      TURNER               30                     BLAKE               
2                      JAMES                30                     BLAKE               
1                      KING                 10                     KING                
2                      CLARK                10                     KING                
3                      MILLER               10                     KING                

14 rows selected

首先,我们找出所有的部门经理的emp_id,然后我们把查询结果作为下个查询的根,查询出我们想要的结果,注意CONNECT_BY_ROOT lname "Top Manager",它直接返回了部门经理的lname,而不是各个员工主管经理的名字。

在一个树形结构中,循环是不允许的,但是在真实世界中,可能会出现这种情况,下面我们考虑修改我们的事例数据,

UPDATE employee
SET manager_emp_id
 = 7654
WHERE manager_emp_id IS NULL;
现在我们的数据中存在一个循环,如果运行一个如下的查询,我们会得到一个错误ORA-01436:
SELECT LEVEL, LPAD('  ',2*(LEVEL - 1)) || lname "EMPLOYEE", 

       emp_id, manager_emp_id

FROM employee

START WITH emp_id = 7839

CONNECT BY PRIOR emp_id = manager_emp_id;



     LEVEL EMPLOYEE                 EMP_ID MANAGER_EMP_ID

---------- -------------------- ---------- --------------

         1 KING                       7839           7654

         2   JONES                    7566           7839

         3     SCOTT                  7788           7566

         4       ADAMS                7876           7788

         3     FORD                   7902           7566

         4       SMITH                7369           7902

         2   BLAKE                    7698           7839

         3     ALLEN                  7499           7698

         3     WARD                   7521           7698

         3     MARTIN                 7654           7698

         4       KING                 7839           7654

         5         JONES              7566           7839

         6           SCOTT            7788           7566

         7             ADAMS          7876           7788

         6           FORD             7902           7566

ERROR:

ORA-01436: CONNECT BY loop in user data







15 rows selected.

在CONNECT BY子句中使用NOCYCLE关键字可以避免这个错误消息,如下:

SELECT LEVEL, LPAD('  ',2*(LEVEL - 1)) || lname "EMPLOYEE", 

       emp_id, manager_emp_id

FROM employee

START WITH emp_id = 7839

CONNECT BY NOCYCLE PRIOR emp_id = manager_emp_id;



     LEVEL EMPLOYEE                 EMP_ID MANAGER_EMP_ID

---------- -------------------- ---------- --------------

         1 KING                       7839           7654

         2   JONES                    7566           7839

         3     SCOTT                  7788           7566

         4       ADAMS                7876           7788

         3     FORD                   7902           7566

         4       SMITH                7369           7902

         2   BLAKE                    7698           7839

         3     ALLEN                  7499           7698

         3     WARD                   7521           7698

         3     MARTIN                 7654           7698

         3     TURNER                 7844           7698

         3     JAMES                  7900           7698

         2   CLARK                    7782           7839

         3     MILLER                 7934           7782

识别循环CONNECT_BY_ISCYCLE伪列,返回1说明存在一个循环。

SELECT lname, CONNECT_BY_ISCYCLE

FROM employee

START WITH emp_id = 7839

CONNECT BY NOCYCLE PRIOR emp_id = manager_emp_id;



LNAME                CONNECT_BY_ISCYCLE

-------------------- ------------------

KING                                  0

JONES                                 0

SCOTT                                 0

ADAMS                                 0

FORD                                  0

SMITH                                 0

BLAKE                                 0

ALLEN                                 0

WARD                                  0

MARTIN                                1

TURNER                                0

JAMES                                 0

CLARK                                 0

MILLER                                0

识别叶节点,CONNECT_BY_ISLEAF,返回值为1则为叶节点。

SELECT lname, CONNECT_BY_ISLEAF

FROM employee

START WITH manager_emp_id IS NULL

CONNECT BY PRIOR emp_id = manager_emp_id;



LNAME           CONNECT_BY_ISLEAF

--------------- -----------------

KING                            0

JONES                           0

SCOTT                           0

ADAMS                           1

FORD                            0

SMITH                           1

BLAKE                           0

ALLEN                           1

WARD                            1

MARTIN                          1

TURNER                          1

JAMES                           1

CLARK                           0

MILLER                          1

 

 

posted on 2007-10-12 10:44 tianjuchuan 阅读(398) 评论(0)  编辑 收藏 引用 所属分类: sql
只有注册用户登录后才能发表评论。