2008-09-17 42 views
4

我想基于它们之间的外键构建表的依赖关系图。此图需要以任意表名作为其根。我可以用给定的表名查找使用all_constraints视图引用它的表,然后查找引用它们的表等等,但这样做效率太差。我写的,这是否对所有表递归查询,但是当我补充一下:使用递归查询构建表依赖关系图

START WITH Table_Name=:tablename 

它不会返回整个树。

回答

8
select parent, child, level from (
select parent_table.table_name parent, child_table.table_name child 
from user_tables  parent_table, 
     user_constraints parent_constraint, 
     user_constraints child_constraint, 
     user_tables  child_table 
where parent_table.table_name = parent_constraint.table_name 
    and parent_constraint.constraint_type IN('P', 'U') 
    and child_constraint.r_constraint_name = parent_constraint.constraint_name 
    and child_constraint.constraint_type = 'R' 
    and child_table.table_name = child_constraint.table_name 
    and child_table.table_name != parent_table.table_name 
) 
start with parent = 'DEPT' 
connect by prior child = parent 

应该工作(更换表名,当然)假设这一切都是在同一个模式。如果您需要处理跨架构依赖性,请为OWNER和R_OWNER列使用数据字典表和条件的DBA_版本。在进一步的反思中,这并没有考虑到自我指涉约束(即MGR列引用EMPNO列的EMP表上的约束),因此如果需要处理,您必须修改代码以处理该案例有自我指涉的限制。

出于测试目的,我增加了一些新表SCOTT模式也引用DEPT表(包括孙子依赖)

SQL> create table dept_child2 (
    2 deptno number references dept(deptno) 
    3 ); 

Table created. 

SQL> create table dept_child3 (
    2 dept_child3_no number primary key, 
    3 deptno number references dept(deptno) 
    4 ); 

Table created. 

SQL> create table dept_grandchild (
    2 dept_child3_no number references dept_child3(dept_child3_no) 
    3 ); 

Table created. 

并验证该查询返回预期输出

SQL> ed 
Wrote file afiedt.buf 

    1 select parent, child, level from (
    2 select parent_table.table_name parent, child_table.table_name child 
    3 from user_tables  parent_table, 
    4  user_constraints parent_constraint, 
    5  user_constraints child_constraint, 
    6  user_tables  child_table 
    7 where parent_table.table_name = parent_constraint.table_name 
    8 and parent_constraint.constraint_type IN('P', 'U') 
    9 and child_constraint.r_constraint_name = parent_constraint.constraint_name 
10 and child_constraint.constraint_type = 'R' 
11 and child_table.table_name = child_constraint.table_name 
12 and child_table.table_name != parent_table.table_name 
13 ) 
14 start with parent = 'DEPT' 
15* connect by prior child = parent 
SQL>/

PARENT       CHILD        LEVEL 
------------------------------ ------------------------------ ---------- 
DEPT       DEPT_CHILD3        1 
DEPT_CHILD3     DEPT_GRANDCHILD       2 
DEPT       DEPT_CHILD2        1 
DEPT       EMP          1 
+0

当我运行该查询,我得到`ORA-01437:不能与CONNECT BY` – 2013-06-20 18:57:25

2

最简单的方式做,这是所有的FK信息复制到一个简单的,2列(父母,子女)表,然后用下面的算法:

while (rows left in that table) 
    list = rows where table name exists in child but not in parent 
    print list 
    remove list from rows 

仅此而已。基本上,您首先打印并删除所有不依赖于任何内容的节点。在完成之后,其他一些节点将获得免费,您可以重复流程。

P.S.确保你不插入自引用表中的初始列表(子=父)