2

Is there faster alternative to this:

Take almost 1 minute in our server.

SELECT
    tc.constraint_name, tc.table_name, kcu.column_name, 
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
    JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' AND tc.table_name='mytable';

Maybe using pg_class metadata?, thanks.

Community
  • 1
  • 1
Najera
  • 2,869
  • 3
  • 28
  • 52
  • 2
    What is it supposed to retrieve exactly? "Foreign keys" is to vague for a description. FK to or from the table? Your question has to make sense for people without running the query. Please clarify. – Erwin Brandstetter Nov 15 '12 at 22:26
  • If that query really takes one minute then I can smell a stinking fish. Either the server is completely swamped or you have a __very__ high number of tables/columns/constraints or ... something else and unusual which you should either solve or mention is this question. – A.H. Nov 15 '12 at 23:36

3 Answers3

2

There is a problem: a foreign key can be on 2 or more columns (FOREIGN KEY (b, c) REFERENCES other_table (c1, c2)). You need to specify first, what to do with such keys.

Here is the query i use to get all the foreign keys, but it works correctly only for simple (one column) foreign keys.

SELECT pgcon.conname as constraint_name, 
       cast(pgcon.conrelid as regclass) as table_name,
       cast(pgcon.confrelid as regclass) as foreign_table_name,
       pga1.attname as column_name,
       pga2.attname as foreign_column_name
FROM pg_constraint pgcon
JOIN pg_attribute pga1 on (pgcon.conrelid = pga1.attrelid
                       and pga1.attnum = any(pgcon.conkey))
JOIN pg_attribute pga2 on (pgcon.confrelid = pga2.attrelid
                       and pga2.attnum = any(pgcon.confkey))
WHERE pgcon.conrelid = cast('table_name_here' as regclass)
  AND pgcon.contype = 'f'
Ihor Romanchenko
  • 26,995
  • 8
  • 48
  • 44
1

To get the same result:

SELECT conname
      ,c.conrelid::regclass AS table_name
      ,(SELECT string_agg(a.attname, ', ') FROM pg_attribute a
        WHERE  a.attrelid = c.conrelid
        AND    a.attnum = ANY(c.conkey)) AS columns
      ,c.confrelid::regclass
      ,(SELECT string_agg(a.attname, ', ') FROM pg_attribute a
        WHERE  a.attrelid = c.confrelid
        AND    a.attnum = ANY(c.confkey)) AS foreign_columns
FROM   pg_constraint c
WHERE  c.conrelid = 'mytable'::regclass
AND    c.contype = 'f'
ORDER  BY c.conname;

Covers foreign keys originating from this table.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
0

You can use the following query:

SELECT conname, pg_get_constraintdef(oid)
  FROM pg_constraint
 WHERE confrelid='mytable'::regclass;

Column confrelid is set only for Foreign Keys and contains referenced table.

This bit is inspired by this depesz's post.

vyegorov
  • 21,787
  • 7
  • 59
  • 73