我在试图建立一个依赖性的曲线图表根据外键他们之间。这个图表,需要开始具有任意表名作为其根源。我可以给出一个表格的名称查表,参考使用的all_constraints查,然后查表,参考他们,等等,但这将是可怕的效率低下。我写了一个递归的查询,这对于所有表格,但是当我添加:

START WITH Table_Name=:tablename

它不返回的整个树。

有帮助吗?

解决方案

    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

应工作(取代表的名字,当然)假设这一切都是在同样的架构。使用DBA_版本的数据字典表和条件的所有者和R_OWNER列如果你需要处理跨架构的依赖关系。在进一步反思,这不考虑对自我引用约束(即一个制约因素EMP表MGR列引用的EMPNO列),所以你必须修改的代码来处理这种情况下,如果您需要处理与自引用的限制。

为测试目的,我加入了一些新的表到斯科特的架构,还参考的部表(包括一个孙子的依赖)

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

其他提示

最简单的方法来做到这一点是复制的所有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.确保你不要插入自引用的表的初步清单(儿童=父)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top