Domanda

Sto cercando di costruire un grafico di dipendenza delle tabelle in base alle chiavi esterne tra loro.Questo grafico deve iniziare con un arbitrario nome della tabella, come radice.Ho potuto, date un nome di tabella cercare le tabelle di riferimento, utilizzando il all_constraints non vista, quindi cercare le tabelle che fanno riferimento a loro, e così via, ma questo sarebbe orribile inefficiente.Ho scritto una query ricorsiva che fa questo per tutte le tabelle, ma quando ho aggiunto:

START WITH Table_Name=:tablename

Non restituire l'intero albero.

È stato utile?

Soluzione

    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

dovrebbe funzionare (sostituire il nome della tabella, naturalmente), supponendo che tutto è nello stesso schema.Utilizzare il DBA_ versioni del dizionario di dati tabelle e le condizioni per il PROPRIETARIO e R_OWNER colonne se avete bisogno di gestire croce-schema di dipendenze.Su ulteriore riflessione, questo non tiene conto per l'auto-referenziale vincoli (es.un vincolo alla tabella EMP che MGR riferimenti di colonna il EMPNO colonna), quindi dovresti modificare il codice per gestire questo caso, se avete a che fare con auto-referenziale vincoli.

Per scopi di test, ho aggiunto un paio di nuove tabelle per la SCOTT schema di riferimento anche il REPARTO tabella (tra cui un nipote di dipendenza)

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.

e verificato che la query ha restituito l'output previsto

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

Altri suggerimenti

Modo più semplice per farlo è quello di copiare tutti i FK informazioni in un semplice, 2-colonna (padre,figlio) della tabella, e quindi utilizzare il seguente 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

questo è tutto.Fondamentalmente, è la prima stampa e rimuovere tutti i nodi che non dipende da nulla.Dopo che è fatto, alcuni altri nodi per ricevere gratuitamente e si può ripetere il processo.

P. S.Assicurarsi di non inserire tabelle autoreferenziali nella lista iniziale (bambino=padre)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top