Pregunta

Estoy tratando de construir un gráfico de dependencia de las tablas basándose en las claves foráneas entre ellos.Este gráfico se necesita para empezar con una tabla arbitraria nombre como su raíz.Yo podría, dado un nombre de tabla de buscar las tablas que hacen referencia a él mediante el all_constraints no ver, a continuación, buscar las tablas que hacen referencia a ellos, y así sucesivamente, pero esto sería horrible ineficiente.Escribí una consulta recursiva que hace esto para todas las tablas, pero cuando agrego:

START WITH Table_Name=:tablename

No se devolverá la totalidad del árbol.

¿Fue útil?

Solución

    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

debería funcionar (reemplazar el nombre de la tabla, por supuesto), suponiendo que todo está en el mismo esquema.El uso de la DBA_ versiones del diccionario de datos de tablas y condiciones para el PROPIETARIO y R_OWNER columnas si usted necesita para manejar la cruz-esquema de dependencias.En más de reflexión, este no tiene en cuenta la auto-referencial de restricciones (es decir,una restricción en la tabla EMP que el GESTOR de referencias de columna de la columna EMPNO), por lo que tendrías que modificar el código para manejar ese caso, si usted necesita para lidiar con la auto-referencial restricciones.

Para propósitos de prueba, he añadido un par de nuevas tablas para el SCOTT esquema que también hacen referencia a la tabla DEPT (incluyendo un nieto de dependencia)

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.

y verificado que la consulta devuelve los resultados esperados

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

Otros consejos

Manera más sencilla de hacer esto es copiar todo el FK información en un simple de la columna 2 (padre,hijo) de la tabla y, a continuación, utilizar el siguiente algoritmo:

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

eso es todo.Básicamente, la primera impresión y eliminar todos los nodos que no dependen de nada.Después de que se hace, algunos otros nodos recibe gratis y se puede repetir el proceso.

P. S.Asegúrese de no insertar la auto-hace referencia a las tablas en la lista inicial (niño=padre)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top