Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL: SQL script to get a list of all tables that have a particular column as foreign key

I'm using PostgreSQL and I'm trying to list all the tables that have a particular column from a table as a foreign-key/reference. Can this be done? I'm sure this information is stored somewhere in information_schema but I have no idea how to start querying it.

like image 397
Gaurav Dadhania Avatar asked Mar 18 '11 01:03

Gaurav Dadhania


People also ask

How can I list all foreign keys referencing a given table in Postgres?

To get a list of all foreign keys of the table using psql you can use the \d your_table_name command line.

How do you identify all foreign key references in a table?

To view the foreign key attributes of a relationship in a specific table. Open the Table Designer for the table containing the foreign key you want to view, right-click in the Table Designer, and choose Relationships from the shortcut menu.


2 Answers

SELECT     r.table_name FROM information_schema.constraint_column_usage       u INNER JOIN information_schema.referential_constraints fk            ON u.constraint_catalog = fk.unique_constraint_catalog                AND u.constraint_schema = fk.unique_constraint_schema                AND u.constraint_name = fk.unique_constraint_name INNER JOIN information_schema.key_column_usage        r            ON r.constraint_catalog = fk.constraint_catalog                AND r.constraint_schema = fk.constraint_schema                AND r.constraint_name = fk.constraint_name WHERE     u.column_name = 'id' AND     u.table_catalog = 'db_name' AND     u.table_schema = 'public' AND     u.table_name = 'table_a' 

This uses the full catalog/schema/name triplet to identify a db table from all 3 information_schema views. You can drop one or two as required.

The query lists all tables that have a foreign key constraint against the column 'a' in table 'd'

like image 88
RichardTheKiwi Avatar answered Oct 13 '22 23:10

RichardTheKiwi


The other solutions are not guaranteed to work in postgresql, as the constraint_name is not guaranteed to be unique; thus you will get false positives. PostgreSQL used to name constraints silly things like '$1', and if you've got an old database you've been maintaining through upgrades, you likely still have some of those around.

Since this question was targeted AT PostgreSQL and that is what you are using, then you can query the internal postgres tables pg_class and pg_attribute to get a more accurate result.

NOTE: FKs can be on multiple columns, thus the referencing column (attnum of pg_attribute) is an ARRAY, which is the reason for using array_agg in the answer.

The only thing you need plug in is the TARGET_TABLE_NAME:

select    (select r.relname from pg_class r where r.oid = c.conrelid) as table,    (select array_agg(attname) from pg_attribute     where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as col,    (select r.relname from pg_class r where r.oid = c.confrelid) as ftable  from pg_constraint c  where c.confrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME'); 

If you want to go the other way (list all of the things a specific table refers to), then just change the last line to:

where c.conrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME'); 

Oh, and since the actual question was to target a specific column, you can specify the column name with this one:

select (select r.relname from pg_class r where r.oid = c.conrelid) as table,         (select array_agg(attname) from pg_attribute          where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as col,         (select r.relname from pg_class r where r.oid = c.confrelid) as ftable  from pg_constraint c  where c.confrelid = (select oid from pg_class where relname = 'TARGET_TABLE_NAME') and        c.confkey @> (select array_agg(attnum) from pg_attribute                      where attname = 'TARGET_COLUMN_NAME' and attrelid = c.confrelid); 
like image 25
Tony K. Avatar answered Oct 14 '22 01:10

Tony K.