L
Let's explore table references by traversing foreign keys. First show all foreign keys for all tables (including multi columns keys).
WITH t (table_name, referenced_table, pk_name, fk_name) AS ( SELECT DISTINCT r.table_name, p.table_name AS referenced_table, p.constraint_name AS pk_name, r.constraint_name AS fk_name FROM user_constraints r JOIN user_constraints p ON r.r_constraint_name = p.constraint_name AND r.constraint_type = 'R' WHERE p.constraint_type = 'P' UNION ALL SELECT NULL, t.table_name, NULL, NULL FROM user_tables t ORDER BY 1, 2 ), c AS ( SELECT r.constraint_name, LISTAGG(c.column_name, ', ') WITHIN GROUP (ORDER BY c.position) AS cols FROM user_cons_columns c JOIN user_constraints r ON r.constraint_name = c.constraint_name WHERE r.constraint_type = 'R' GROUP BY r.constraint_name ) SELECT LPAD(' ', (LEVEL - 1) * 2) || t.referenced_table AS table_name, t.fk_name, c.cols, t.pk_name FROM t LEFT JOIN c ON c.constraint_name = t.fk_name CONNECT BY NOCYCLE PRIOR t.referenced_table = t.table_name START WITH t.table_name IS NULL ORDER SIBLINGS BY t.table_name;
For small schemas you can also try this:
SELECT p.table_name, LISTAGG(r.table_name, ', ') WITHIN GROUP (ORDER BY r.table_name) AS referred_tables FROM user_constraints r JOIN user_constraints p ON p.r_constraint_name = r.constraint_name AND p.constraint_type = 'R' WHERE r.constraint_type = 'P' GROUP BY p.table_name ORDER BY p.table_name;
Now let's try the opposite. Select all tables with referenced tables (and columns).
WITH c AS ( SELECT r.constraint_name, LISTAGG(c.column_name, ', ') WITHIN GROUP (ORDER BY c.position) AS cols FROM user_cons_columns c JOIN user_constraints r ON r.constraint_name = c.constraint_name WHERE r.constraint_type = 'R' GROUP BY r.constraint_name ) SELECT CASE WHEN t.referenced_table IS NULL THEN t.table_name ELSE ' ' || t.referenced_table END AS table_name, t.fk_name, c.cols FROM ( SELECT DISTINCT p.table_name, r.table_name AS referenced_table, r.constraint_name AS fk_name FROM user_constraints r JOIN user_constraints p ON p.constraint_name = r.r_constraint_name AND p.constraint_type = 'P' WHERE r.constraint_type = 'R' UNION ALL SELECT t.table_name, NULL, NULL FROM user_tables t ) t LEFT JOIN c ON c.constraint_name = t.fk_name ORDER BY t.table_name, t.referenced_table NULLS FIRST;
For small schemas you can also try this:
SELECT p.table_name, LISTAGG(r.table_name, ', ') WITHIN GROUP (ORDER BY r.table_name) AS references FROM user_constraints r JOIN user_constraints p ON p.constraint_name = r.r_constraint_name AND p.constraint_type = 'P' WHERE r.constraint_type = 'R' GROUP BY p.table_name ORDER BY p.table_name;
Comments
Post a Comment