Postgres: SQL para listar chaves estrangeiras da tabela

219

Existe uma maneira de usar o SQL para listar todas as chaves estrangeiras para uma determinada tabela? Conheço o nome da tabela / esquema e posso conectá-lo.

smack0007
fonte
Sugiro usar a resposta do @Magnus . Mais simples, mais limpo, mais rápido.
Erwin Brandstetter

Respostas:

373

Você pode fazer isso através das tabelas information_schema. Por exemplo:

SELECT
    tc.table_schema, 
    tc.constraint_name, 
    tc.table_name, 
    kcu.column_name, 
    ccu.table_schema AS foreign_table_schema,
    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
      AND tc.table_schema = kcu.table_schema
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
      AND ccu.table_schema = tc.table_schema
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='mytable';
ollyc
fonte
8
table_name = 'mytable' deve ser tc.table_name = 'mytable' ou então gera um erro ambíguo
intrepion
15
+1, muito útil. Para tornar a consulta mais robusta, provavelmente também deve se juntar ao constraint_schema, já que é possível que dois esquemas tenham restrições com o mesmo nome. Algo como: FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu USING (constraint_schema, constraint_name) JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
EMP
8
Isso é interrompido quando há várias colunas em uma restrição, não é? Parece não haver uma maneira adequada de associar colunas pk a colunas fk usando o information_schema BTW.
Fionbio
5
Na verdade, ele quebra com mais de uma coluna em restrição. Para o Postgres, existe uma maneira de obter essas informações do esquema pg_catalog. Veja minha resposta abaixo.
martin
9
A consulta está errada. Ele pressupõe que os nomes de restrição não possam ser repetidos, o que é falso. Restrições com o mesmo nome podem existir em diferentes espaços para nome. Você está usando constraint_name para fazer a junção. A junção de nomes de restrição e nome do esquema não funcionará, pois você não tem certeza de que as duas restrições são iguais. A única opção é usar pg_constraints, pg_class etc. usando oids para participar. O catálogo ANSI do Postgres está disponível apenas para conformidade, mas é falho. pg_catalog é o caminho a percorrer. A resposta correta é aqui dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova
69

O psql faz isso e se você iniciar o psql com:

psql -E

mostrará exatamente qual consulta é executada. No caso de encontrar chaves estrangeiras, é:

SELECT conname,
  pg_catalog.pg_get_constraintdef(r.oid, true) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid = '16485' AND r.contype = 'f' ORDER BY 1

Nesse caso, 16485 é o oid da tabela que estou vendo - você pode obtê-lo simplesmente lançando seu nome de tabela para regclassar como:

WHERE r.conrelid = 'mytable'::regclass

Qualifique o nome da tabela se ele não for exclusivo (ou o primeiro no seu search_path):

WHERE r.conrelid = 'myschema.mytable'::regclass
Magnus Hagander
fonte
2
Isso é muito útil! O Postgres parece ter um milhão de pequenas funções como essa que simplificam tudo. Agora, como se lembrar deles?
Epic_fil
5
@ Phil: Você só precisa de uma ideia geral. Deixe o manual lembrar o resto.
Erwin Brandstetter
3
para listar todas as chaves estrangeiras direcionadas a uma tabela:SELECT conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.confrelid = 'myschema.mytable'::regclass;
regilero 20/10
1
@ErwinBrandstetter como faço para obter um nome de tabela estrangeira?
Wellington Silva Ribeiro
2
Não entendi, qual comando deve ser usado? psql -E -U username -d database ThenWHAT?
Poutrathor 17/01/19
49

Problema \d+ tablenameno prompt do PostgreSQL, além de mostrar os tipos de dados da coluna da tabela, ele mostra os índices e as chaves estrangeiras.

Gre Hahn
fonte
Lamento não ter notado que meu comentário foi cortado. Se você pudesse pelo menos tentar uma vez, também veria o mapeamento de chaves estrangeiras.
Gre Hahn
45

A resposta de Ollyc é boa, pois não é específica do Postgres, no entanto, é interrompida quando a chave estrangeira faz referência a mais de uma coluna. A consulta a seguir funciona para um número arbitrário de colunas, mas depende muito das extensões do Postgres:

select 
    att2.attname as "child_column", 
    cl.relname as "parent_table", 
    att.attname as "parent_column",
    conname
from
   (select 
        unnest(con1.conkey) as "parent", 
        unnest(con1.confkey) as "child", 
        con1.confrelid, 
        con1.conrelid,
        con1.conname
    from 
        pg_class cl
        join pg_namespace ns on cl.relnamespace = ns.oid
        join pg_constraint con1 on con1.conrelid = cl.oid
    where
        cl.relname = 'child_table'
        and ns.nspname = 'child_schema'
        and con1.contype = 'f'
   ) con
   join pg_attribute att on
       att.attrelid = con.confrelid and att.attnum = con.child
   join pg_class cl on
       cl.oid = con.confrelid
   join pg_attribute att2 on
       att2.attrelid = con.conrelid and att2.attnum = con.parent
Martin
fonte
antes da 8.4, a função unnest deve ser criada primeiro. wiki.postgresql.org/wiki/Array_Unnest
maletin
Onde se insere o nome da tabela nessa consulta? O texto inserido acima retorna 0 linhas no meu banco de dados PSQL que possui dezenas de chaves estrangeiras.
Phrogz
4
Você substituir 'child_table' e 'child_schema' com os nomes da tabela e seu esquema
martin
isso não informa o nome da chave.
Evan Carroll
@EvanCarroll Atualizei minha resposta para incluir o nome da chave.
martin
31

Extensão à receita ollyc:

CREATE VIEW foreign_keys_view AS
SELECT
    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';

Então:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';

Mvoicem
fonte
Obrigado, ideal para reutilizar.
21317 schellingerht
16

verifique o post ff para a sua solução e não se esqueça de marcar isso quando você achar isso útil

http://errorbank.blogspot.com/2011/03/list-all-foreign-keys-references-for.html

SELECT
  o.conname AS constraint_name,
  (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema,
  m.relname AS source_table,
  (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column,
  (SELECT nspname FROM pg_namespace WHERE oid=f.relnamespace) AS target_schema,
  f.relname AS target_table,
  (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column
FROM
  pg_constraint o LEFT JOIN pg_class f ON f.oid = o.confrelid LEFT JOIN pg_class m ON m.oid = o.conrelid
WHERE
  o.contype = 'f' AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r');
Sheldon
fonte
Oferece dois SQLs que funcionam no PostgreSQL 9.1 (depois que você corrigir o escape errado, coloque seu 'tablename' (sem prefixo do esquema) no SQL).
Alfonx
2
+1: esta é a única solução que não retorna duplicatas.
precisa
para esta solução, funciona bem e não retorna duplicatas.
Fuhrmann
1
Esta solução mostrará apenas a primeira coluna de qualquer chave estrangeira de várias colunas ... mas parece muito mais simples do que a que acabei de publicar que fará múltiplos.
DEWIN
12

Esta consulta funciona corretamente com chaves compostas também:

select c.constraint_name
    , x.table_schema as schema_name
    , x.table_name
    , x.column_name
    , y.table_schema as foreign_schema_name
    , y.table_name as foreign_table_name
    , y.column_name as foreign_column_name
from information_schema.referential_constraints c
join information_schema.key_column_usage x
    on x.constraint_name = c.constraint_name
join information_schema.key_column_usage y
    on y.ordinal_position = x.position_in_unique_constraint
    and y.constraint_name = c.unique_constraint_name
order by c.constraint_name, x.ordinal_position
oscavi
fonte
2
Você está ingressando nas colunas em "nome da restrição", portanto isso funcionará apenas se todos os seus nomes de restrição forem exclusivos (em todas as tabelas em todos os esquemas). Isso geralmente não é um requisito e, portanto, não é imposto pelo banco de dados.
Zilk
3
Obrigado. Esta é a única resposta que mostra como usar o information_schema para manipular corretamente várias colunas.
Samuel Danielson
Esta solução funciona. Não produz duplicatas e lida com vários campos no FK.
Igor
9

Eu acho que o que você estava procurando e muito próximo do que a @ollyc escreveu é o seguinte:

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 ccu.table_name='YourTableNameHere';

Isso listará todas as tabelas que usam sua tabela especificada como uma chave estrangeira

Shaun McCready
fonte
9

voto curto, mas doce, se funcionar para você.

select  * from information_schema.key_column_usage where constraint_catalog=current_catalog and table_name='your_table_name' and position_in_unique_constraint notnull;
NikhilP
fonte
Trabalhou um encanto como eu escrevo com PG 12.2
Jack Kinsella
5

Nenhuma das respostas existentes me deu resultados da forma que eu realmente queria. Então, aqui está minha (gigantesca) consulta para encontrar informações sobre chaves estrangeiras.

Algumas notas:

  • As expressões usadas para gerar from_colse to_colspodem ser bastante simplificadas no Postgres 9.4 e posterior usandoWITH ORDINALITY em vez da hackery que usa as funções da janela que estou usando.
  • Essas mesmas expressões dependem do planejador de consultas que não altera a ordem de resultados retornada de UNNEST . Acho que não, mas não tenho chaves estrangeiras de várias colunas no meu conjunto de dados para testar. A adição das 9,4 sutilezas elimina completamente essa possibilidade.
  • A consulta em si requer o Postgres 9.0 ou posterior (8.x não permite ORDER BYfunções agregadas)
  • Substitua STRING_AGGpor ARRAY_AGGse desejar uma matriz de colunas em vez de uma sequência separada por vírgula.

-

SELECT
    c.conname AS constraint_name,
    (SELECT n.nspname FROM pg_namespace AS n WHERE n.oid=c.connamespace) AS constraint_schema,

    tf.name AS from_table,
    (
        SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq)
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
                    attnum
                FROM
                    UNNEST(c.conkey) AS t(attnum)
            ) AS t
            INNER JOIN pg_attribute AS a ON a.attrelid=c.conrelid AND a.attnum=t.attnum
    ) AS from_cols,

    tt.name AS to_table,
    (
        SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq)
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
                    attnum
                FROM
                    UNNEST(c.confkey) AS t(attnum)
            ) AS t
            INNER JOIN pg_attribute AS a ON a.attrelid=c.confrelid AND a.attnum=t.attnum
    ) AS to_cols,

    CASE confupdtype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_update,
    CASE confdeltype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_delete,
    CASE confmatchtype::text WHEN 'f' THEN 'full' WHEN 'p' THEN 'partial' WHEN 'u' THEN 'simple' WHEN 's' THEN 'simple' ELSE NULL END AS match_type,  -- In earlier postgres docs, simple was 'u'nspecified, but current versions use 's'imple.  text cast is required.

    pg_catalog.pg_get_constraintdef(c.oid, true) as condef
FROM
    pg_catalog.pg_constraint AS c
    INNER JOIN (
        SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name
        FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
    ) AS tf ON tf.oid=c.conrelid
    INNER JOIN (
        SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name
        FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
    ) AS tt ON tt.oid=c.confrelid
WHERE c.contype = 'f' ORDER BY 1;
dewin
fonte
5

Um outro caminho:

WITH foreign_keys AS (
    SELECT
      conname,
      conrelid,
      confrelid,
      unnest(conkey)  AS conkey,
      unnest(confkey) AS confkey
    FROM pg_constraint
    WHERE contype = 'f' -- AND confrelid::regclass = 'your_table'::regclass
)
-- if confrelid, conname pair shows up more than once then it is multicolumn foreign key
SELECT fk.conname as constraint_name,
       fk.confrelid::regclass as referenced_table, af.attname as pkcol,
       fk.conrelid::regclass as referencing_table, a.attname as fkcol
FROM foreign_keys fk
JOIN pg_attribute af ON af.attnum = fk.confkey AND af.attrelid = fk.confrelid
JOIN pg_attribute a ON a.attnum = conkey AND a.attrelid = fk.conrelid
ORDER BY fk.confrelid, fk.conname
;
Konrad Perzyna
fonte
4

Use o nome da Chave Primária à qual as Chaves estão fazendo referência e consulte o information_schema:

select table_name, column_name
from information_schema.key_column_usage
where constraint_name IN (select constraint_name
  from information_schema.referential_constraints 
  where unique_constraint_name = 'TABLE_NAME_pkey')

Aqui 'TABLE_NAME_pkey' é o nome da chave primária referenciada pelas chaves estrangeiras.

markmnl
fonte
4

Aqui está uma solução de Andreas Joseph Krogh da lista de discussão do PostgreSQL: http://www.postgresql.org/message-id/[email protected]

SELECT source_table::regclass, source_attr.attname AS source_column,
    target_table::regclass, target_attr.attname AS target_column
FROM pg_attribute target_attr, pg_attribute source_attr,
  (SELECT source_table, target_table, source_constraints[i] source_constraints, target_constraints[i] AS target_constraints
   FROM
     (SELECT conrelid as source_table, confrelid AS target_table, conkey AS source_constraints, confkey AS target_constraints,
       generate_series(1, array_upper(conkey, 1)) AS i
      FROM pg_constraint
      WHERE contype = 'f'
     ) query1
  ) query2
WHERE target_attr.attnum = target_constraints AND target_attr.attrelid = target_table AND
      source_attr.attnum = source_constraints AND source_attr.attrelid = source_table;

Esta solução lida com chaves estrangeiras que fazem referência a várias colunas e evita duplicatas (o que algumas das outras respostas não conseguem fazer). A única coisa que mudei foram os nomes das variáveis.

Aqui está um exemplo que retorna todas as employeecolunas que fazem referência à permissiontabela:

SELECT source_column
FROM foreign_keys
WHERE source_table = 'employee'::regclass AND target_table = 'permission'::regclass;
Gili
fonte
4

Para expandir a excelente resposta de Martin, aqui está uma consulta que permite filtrar com base na tabela pai e mostra o nome da tabela filho com cada tabela pai, para que você possa ver todas as tabelas / colunas dependentes com base nas restrições de chave estrangeira em a tabela pai.

select 
    con.constraint_name,
    att2.attname as "child_column", 
    cl.relname as "parent_table", 
    att.attname as "parent_column",
    con.child_table,
    con.child_schema
from
   (select 
        unnest(con1.conkey) as "parent", 
        unnest(con1.confkey) as "child", 
        con1.conname as constraint_name,
        con1.confrelid, 
        con1.conrelid,
        cl.relname as child_table,
        ns.nspname as child_schema
    from 
        pg_class cl
        join pg_namespace ns on cl.relnamespace = ns.oid
        join pg_constraint con1 on con1.conrelid = cl.oid
    where  con1.contype = 'f'
   ) con
   join pg_attribute att on
       att.attrelid = con.confrelid and att.attnum = con.child
   join pg_class cl on
       cl.oid = con.confrelid
   join pg_attribute att2 on
       att2.attrelid = con.conrelid and att2.attnum = con.parent
   where cl.relname like '%parent_table%'       
Cervo
fonte
1
A consulta na resposta aceita adiciona 1,2 segundos a uma consulta de ~ 0,03; a sua adiciona apenas 0,01, obrigado!
AVProgrammer
3

Solução adequada para o problema, usando information_schema, trabalhando com chaves de várias colunas, unindo colunas de nomes diferentes nas duas tabelas corretamente e também compatível com o ms sqlsever:

select fks.TABLE_NAME as foreign_key_table_name
, fks.CONSTRAINT_NAME as foreign_key_constraint_name
, kcu_foreign.COLUMN_NAME as foreign_key_column_name
, rc.UNIQUE_CONSTRAINT_NAME as primary_key_constraint_name
, pks.TABLE_NAME as primary_key_table_name
, kcu_primary.COLUMN_NAME as primary_key_column_name
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS fks -- foreign keys
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu_foreign -- the columns of the above keys
    on fks.TABLE_CATALOG = kcu_foreign.TABLE_CATALOG
    and fks.TABLE_SCHEMA = kcu_foreign.TABLE_SCHEMA
    and fks.TABLE_NAME = kcu_foreign.TABLE_NAME
    and fks.CONSTRAINT_NAME = kcu_foreign.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc -- referenced constraints
    on rc.CONSTRAINT_CATALOG = fks.CONSTRAINT_CATALOG
    and rc.CONSTRAINT_SCHEMA = fks.CONSTRAINT_SCHEMA
    and rc.CONSTRAINT_NAME = fks.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS pks -- primary keys (referenced by fks)
    on rc.UNIQUE_CONSTRAINT_CATALOG = pks.CONSTRAINT_CATALOG
    and rc.UNIQUE_CONSTRAINT_SCHEMA = pks.CONSTRAINT_SCHEMA
    and rc.UNIQUE_CONSTRAINT_NAME = pks.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu_primary
    on pks.TABLE_CATALOG = kcu_primary.TABLE_CATALOG
    and pks.TABLE_SCHEMA = kcu_primary.TABLE_SCHEMA
    and pks.TABLE_NAME = kcu_primary.TABLE_NAME
    and pks.CONSTRAINT_NAME = kcu_primary.CONSTRAINT_NAME
    and kcu_foreign.ORDINAL_POSITION = kcu_primary.ORDINAL_POSITION -- this joins the columns
where fks.TABLE_SCHEMA = 'dbo' -- replace with schema name
and fks.TABLE_NAME = 'your_table_name' -- replace with table name
and fks.CONSTRAINT_TYPE = 'FOREIGN KEY'
and pks.CONSTRAINT_TYPE = 'PRIMARY KEY'
order by fks.constraint_name, kcu_foreign.ORDINAL_POSITION

Nota: Existem algumas diferenças entre as implementações do potgresql e do sqlserver, information_schemaque fazem com que a resposta superior dê resultados diferentes nos dois sistemas - um mostra os nomes das colunas da tabela de chaves estrangeiras e o outro da tabela de chaves primárias. Por esse motivo, decidi usar a exibição KEY_COLUMN_USAGE.

jakubiszon
fonte
O esquema de informações parece ser a resposta certa, mas você realmente deseja as tabelas pg_catalog: pg_constraint etc. Se o seu banco de dados tem grandes quantidades de restrições pode haver problemas de desempenho ...
hajikelist
A condição acima ativada ORDINAL_POSITIONpode gerar um resultado incorreto quando a ordem das colunas na chave estrangeira é diferente da ordem das colunas na restrição exclusiva. Eu acredito que você deve se juntaram em kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Atualização : Além disso, uma chave estrangeira pode depender de uma restrição UNIQUE, bem, então eu acho que você deve remover a pks.CONSTRAINT_TYPEcondição e pode apenas participar rcde kcu_primarydiretamente
EASD
Eu fiz uma resposta semelhante aqui: stackoverflow.com/a/62260908/9093051
easd
2
SELECT r.conname
      ,ct.table_name
      ,pg_catalog.pg_get_constraintdef(r.oid, true) as condef
  FROM pg_catalog.pg_constraint r, information_schema.constraint_table_usage ct
 WHERE r.contype = 'f' 
   AND r.conname = ct.constraint_name
 ORDER BY 1
Pugazendhi Asaimuthu
fonte
2

Eu escrevi uma solução que gosta e usa com freqüência. O código está em http://code.google.com/p/pgutils/ . Veja a visualização pgutils.foreign_keys.

Infelizmente, a saída é muito extensa para incluir aqui. No entanto, você pode experimentá-lo em uma versão pública do banco de dados aqui, assim:

$ psql -h unison-db.org -U PUBLIC -d unison -c 'select * from pgutils.foreign_keys;

Isso funciona com 8.3, pelo menos. Antecipo atualizá-lo, se necessário, nos próximos meses.

-Reece

Reece
fonte
1
O link do projeto está morto agora.
Pimlottc 9/09/14
@pimlottc: Movido para bitbucket.org/reece/pgutils . Obrigado por apontar isso.
Reece
1

Criei uma pequena ferramenta para consultar e comparar o esquema do banco de dados: Dump PostgreSQL db schema to text

Há informações sobre o FK, mas a resposta do ollyc fornece mais detalhes.

Michał Niklas
fonte
0

Nota: Não esqueça a ordem das colunas ao ler as colunas de restrição!

SELECT conname, attname
  FROM pg_catalog.pg_constraint c 
  JOIN pg_catalog.pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY (c.conkey)
 WHERE attrelid = 'schema.table_name'::regclass
 ORDER BY conname, array_position(c.conkey, a.attnum)
Nashev
fonte
0

Isto é o que estou usando atualmente, ele listará uma tabela e suas restrições de fkey [remover a cláusula de tabela e listará todas as tabelas no catálogo atual]:

SELECT

    current_schema() AS "schema",
    current_catalog AS "database",
    "pg_constraint".conrelid::regclass::text AS "primary_table_name",
    "pg_constraint".confrelid::regclass::text AS "foreign_table_name",

    (
        string_to_array(
            (
                string_to_array(
                    pg_get_constraintdef("pg_constraint".oid),
                    '('
                )
            )[2],
            ')'
        )
    )[1] AS "foreign_column_name",

    "pg_constraint".conindid::regclass::text AS "constraint_name",

    TRIM((
        string_to_array(
            pg_get_constraintdef("pg_constraint".oid),
            '('
        )
    )[1]) AS "constraint_type",

    pg_get_constraintdef("pg_constraint".oid) AS "constraint_definition"

FROM pg_constraint AS "pg_constraint"

JOIN pg_namespace AS "pg_namespace" ON "pg_namespace".oid = "pg_constraint".connamespace

WHERE
    --fkey and pkey constraints
    "pg_constraint".contype IN ( 'f', 'p' )
    AND
    "pg_namespace".nspname = current_schema()
    AND
    "pg_constraint".conrelid::regclass::text IN ('whatever_table_name')
hajikelist
fonte
0

o mais rápido a verificar a resposta direta no bash com base inteiramente nessa resposta

IFS='' read -r -d '' sql_code << EOF_SQL_CODE
      SELECT
      o.oid
      , o.conname AS constraint_name
      , (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema
      , m.relname AS source_table
      , (SELECT a.attname FROM pg_attribute a
      WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column
      , (SELECT nspname FROM pg_namespace
      WHERE oid=f.relnamespace) AS target_schema
      , f.relname AS target_table
      , (SELECT a.attname FROM pg_attribute a
      WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column
      , ROW_NUMBER () OVER (ORDER BY o.oid) as rowid
      FROM pg_constraint o
      LEFT JOIN pg_class f ON f.oid = o.confrelid
      LEFT JOIN pg_class m ON m.oid = o.conrelid
      WHERE 1=1
      AND o.contype = 'f'
      AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r')
EOF_SQL_CODE

psql -d my_db -c "$sql_code"
Yordan Georgiev
fonte