una tablas tabla saber relacionadas quien que ora modifico modificar llaves identidad foraneas estan desea dependencias consultar como columna campo autoincremental auto_increment 12c 11g database oracle database-schema

database - tablas - identity oracle 11g



¿Cómo encontrar dependencias de clave externa que apuntan a un registro en Oracle? (6)

Podemos usar el diccionario de datos para identificar las tablas que hacen referencia a la clave principal de la tabla en cuestión. De eso podemos generar algunos SQL dinámicos para consultar esas tablas para el valor que queremos borrar:

SQL> declare 2 n pls_integer; 3 tot pls_integer := 0; 4 begin 5 for lrec in ( select table_name from user_constraints 6 where r_constraint_name = ''T23_PK'' ) 7 loop 8 execute immediate ''select count(*) from ''||lrec.table_name 9 ||'' where col2 = :1'' into n using &&target_val; 10 if n = 0 then 11 dbms_output.put_line(''No impact on ''||lrec.table_name); 12 else 13 dbms_output.put_line(''Uh oh! ''||lrec.table_name||'' has ''||n||'' hits!''); 14 end if; 15 tot := tot + n; 16 end loop; 17 if tot = 0 18 then 19 delete from t23 where col2 = &&target_val; 20 dbms_output.put_line(''row deleted!''); 21 else 22 dbms_output.put_line(''delete aborted!''); 23 end if; 24 end; 25 / Enter value for target_val: 6 No impact on T34 Uh oh! T42 has 2 hits! No impact on T69 delete aborted! PL/SQL procedure successfully completed. SQL>

Este ejemplo hace trampa un poco. El nombre de la clave primaria de destino está codificado, y la columna de referencia tiene el mismo nombre en todas las tablas dependientes. La solución de estos problemas se deja como un ejercicio para el lector;)

Tengo una base de datos Oracle muy grande, con muchas tablas y millones de filas. Necesito eliminar uno de ellos, pero quiero asegurarme de que al eliminarlo no se rompa ninguna otra fila dependiente que lo señale como un registro de clave externa. ¿Hay alguna manera de obtener una lista de todos los otros registros, o al menos los esquemas de tabla, que apuntan a esta fila? Sé que podría intentar eliminarlo yo mismo y atrapar la excepción, pero no ejecutaré el script yo mismo y necesitaré que se ejecute limpio la primera vez.

Tengo las herramientas SQL Developer de Oracle y PL / SQL Developer de AllRoundAutomations a mi disposición.

¡Gracias por adelantado!


Siempre miro las claves foráneas para la mesa de inicio y vuelvo a trabajar. Las herramientas de DB generalmente tienen un nodo de dependencias o restricciones. Sé que L / SQL Developer tiene una forma de ver los FK, pero ha pasado un tiempo desde que lo usé, así que no puedo explicarlo ...

simplemente reemplace XXXXXXXXXXXX con un nombre de tabla ...

/* The following query lists all relationships */ select a.owner||''.''||a.table_name "Referenced Table" ,b.owner||''.''||b.table_name "Referenced by" ,b.constraint_name "Foreign Key" from all_constraints a, all_constraints b where b.constraint_type = ''R'' and a.constraint_name = b.r_constraint_name and b.table_name=''XXXXXXXXXXXX'' -- Table name order by a.owner||''.''||a.table_name


Recientemente tuve un problema similar, pero experimenté pronto, que encontrar las dependencias directas no es suficiente. Así que escribí una consulta para mostrar un árbol de dependencias de clave externa multinivel:

SELECT LPAD('' '',4*(LEVEL-1)) || table1 || '' <-- '' || table2 tables, table2_fkey FROM (SELECT a.table_name table1, b.table_name table2, b.constraint_name table2_fkey FROM user_constraints a, user_constraints b WHERE a.constraint_type IN(''P'', ''U'') AND b.constraint_type = ''R'' AND a.constraint_name = b.r_constraint_name AND a.table_name != b.table_name AND b.table_name <> ''MYTABLE'') CONNECT BY PRIOR table2 = table1 AND LEVEL <= 5 START WITH table1 = ''MYTABLE'';

Da un resultado como este cuando se usa SHIPMENT como MYTABLE en mi base de datos:

SHIPMENT <-- ADDRESS SHIPMENT <-- PACKING_LIST PACKING_LIST <-- PACKING_LIST_DETAILS PACKING_LIST <-- PACKING_UNIT PACKING_UNIT <-- PACKING_LIST_ITEM PACKING_LIST <-- PO_PACKING_LIST ...


Me sorprendió lo difícil que era encontrar el orden de dependencia de las tablas en función de las relaciones de claves externas. Lo necesitaba porque quería eliminar los datos de todas las tablas e importarlas de nuevo. Aquí está la consulta que escribí para enumerar las tablas en orden de dependencia. Pude guiar las eliminaciones usando la consulta a continuación e importar de nuevo usando los resultados de la consulta en orden inverso.

SELECT referenced_table ,MAX(lvl) for_deleting ,MIN(lvl) for_inserting FROM ( -- Hierarchy of dependencies SELECT LEVEL lvl ,t.table_name referenced_table ,b.table_name referenced_by FROM user_constraints A JOIN user_constraints b ON A.constraint_name = b.r_constraint_name and b.constraint_type = ''R'' RIGHT JOIN user_tables t ON t.table_name = A.table_name START WITH b.table_name IS NULL CONNECT BY b.table_name = PRIOR t.table_name ) GROUP BY referenced_table ORDER BY for_deleting, for_inserting;


Las restricciones de Oracle usan índices de tabla para los datos de referencia.
Para averiguar qué tablas hacen referencia a una tabla, simplemente busque el índice en orden inverso.

/* Toggle ENABLED and DISABLE status for any referencing constraint: */ select ''ALTER TABLE ''||b.owner||''.''||b.table_name||'' ''|| decode(b.status, ''ENABLED'', ''DISABLE '', ''ENABLE '')|| ''CONSTRAINT ''||b.constraint_name||'';'' from all_indexes a, all_constraints b where a.table_name=''XXXXXXXXXXXX'' -- Table name and a.index_name = b.r_constraint_name;

Obs .: la desactivación de referencias mejora considerablemente el tiempo de los comandos DML (actualizar, eliminar e insertar).

Esto puede ayudar mucho en operaciones masivas, donde sabe que todos los datos son consistentes.

/* List which columns are referenced in each constraint */ select '' TABLE "''||b.owner||''.''||b.table_name||''"''|| ''(''||listagg (c.column_name, '','') within group (order by c.column_name)||'')''|| '' FK "''||b.constraint_name||''" -> ''||a.table_name|| '' INDEX "''||a.index_name||''"'' "REFERENCES" from all_indexes a, all_constraints b, all_cons_columns c where rtrim(a.table_name) like ''XXXXXXXXXXXX'' -- Table name and a.index_name = b.r_constraint_name and c.constraint_name = b.constraint_name group by b.owner, b.table_name, b.constraint_name, a.table_name, a.index_name order by 1;


Aquí está mi solución para enumerar todas las referencias a una tabla:

select src_cc.owner as src_owner, src_cc.table_name as src_table, src_cc.column_name as src_column, dest_cc.owner as dest_owner, dest_cc.table_name as dest_table, dest_cc.column_name as dest_column, c.constraint_name from all_constraints c inner join all_cons_columns dest_cc on c.r_constraint_name = dest_cc.constraint_name and c.r_owner = dest_cc.owner inner join all_cons_columns src_cc on c.constraint_name = src_cc.constraint_name and c.owner = src_cc.owner where c.constraint_type = ''R'' and dest_cc.owner = ''MY_TARGET_SCHEMA'' and dest_cc.table_name = ''MY_TARGET_TABLE'' --and dest_cc.column_name = ''MY_OPTIONNAL_TARGET_COLUMN'' ;

Con esta solución, también tiene la información de qué columna de qué tabla está haciendo referencia a qué columna de su tabla de destino (y puede filtrarla).