Postgres: SQL per elencare le chiavi esterne della tabella


Risposte:


373

Puoi farlo tramite le tabelle information_schema. Per esempio:

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';

8
table_name = 'mytable' dovrebbe essere tc.table_name = 'mytable' oppure genera un errore ambiguo
intrepion

15
+1, molto utile. Per rendere la query più robusta, probabilmente dovrebbe unirsi anche a binding_schema, poiché è possibile che due schemi abbiano vincoli con lo stesso nome. Qualcosa del tipo: 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
Questo si interrompe quando ci sono più colonne in un vincolo, non è vero? Sembra che non ci sia un modo corretto di associare colonne pk a colonne fk usando information_schema BTW.
fionbio,

5
In effetti si rompe con più di una colonna vincolata. Per Postgres esiste un modo per ottenere queste informazioni dallo schema pg_catalog. Vedi la mia risposta qui sotto.
martin

9
La query è sbagliata. Presuppone che i nomi dei vincoli non possano essere ripetuti, il che è falso. Vincoli con lo stesso nome possono esistere in spazi dei nomi diversi. Stai usando restring_name per creare il join. Anche l'unione sia sul nome_controllo che sul nome dello schema non funzionerà poiché non sei sicuro che i due vincoli siano uguali. L'unica opzione sta per pg_constraints, pg_class ecc. Utilizzando oids per unirsi. Il catalogo ANSI di Postgres è lì solo per conformità ma è difettoso. pg_catalog è la strada da percorrere. La risposta corretta è qui dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova

69

psql fa questo, e se avvii psql con:

psql -E

ti mostrerà esattamente quale query viene eseguita. Nel caso di trovare chiavi esterne, è:

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

In questo caso, 16485 è l'ide del tavolo che sto guardando - puoi ottenerlo semplicemente lanciando il tuo nome tab per registrarti come:

WHERE r.conrelid = 'mytable'::regclass

Qualifica schema il nome della tabella se non è univoco (o il primo nel tuo search_path):

WHERE r.conrelid = 'myschema.mytable'::regclass

2
Questo è molto utile! Postgres sembra avere un milione di piccole funzioni come questa che rendono tutto più semplice. Ora come ricordarli?
epic_fil,

5
@Phil: hai solo bisogno di un'idea generale. Lascia che il manuale ricordi il resto.
Erwin Brandstetter,

3
per elencare tutte le chiavi esterne destinate a un tavolo: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

1
@ErwinBrandstetter come posso ottenere un nome di tabella straniera?
Wellington Silva Ribeiro,

2
Non capisco, quale comando dovrebbe essere usato? psql -E -U username -d database ThenWHAT?
Poutrathor,

49

Emissione \d+ tablenamesul prompt di PostgreSQL, oltre a mostrare i tipi di dati della colonna della tabella mostrerà gli indici e le chiavi esterne.


Spiacenti, non ho notato che il mio commento è stato ritagliato. Se potessi almeno provarlo una volta, visualizzerai anche le mappature delle chiavi esterne.
Gre Hahn,

45

La risposta di Ollyc è buona in quanto non è specifica di Postgres, tuttavia si interrompe quando la chiave esterna fa riferimento a più di una colonna. La seguente query funziona per un numero arbitrario di colonne ma si basa fortemente sulle estensioni di 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

prima della 8.4 è necessario creare inizialmente la funzione unestest. wiki.postgresql.org/wiki/Array_Unnest
maletin

Dove si inserisce il nome della tabella in questa query? Inserito alla lettera quanto sopra restituisce 0 righe sul mio DB PSQL che ha decine di chiavi esterne.
Phrogz,

4
Sostituisci 'child_table' e 'child_schema' con i nomi della tabella e il suo schema
martin

questo non ti dice il nome del fkey.
Evan Carroll,

@EvanCarroll Ho aggiornato la mia risposta per includere il nome della chiave.
Martin

31

Estensione alla ricetta 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';

Poi:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';


Grazie, ideale per il riutilizzo.
schellingerht,

16

controlla il post su ff per la tua soluzione e non dimenticare di contrassegnarlo quando lo ritieni utile

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');

Offre due SQL che funzionano su PostgreSQL 9.1 (una volta corretta la fuga errata, inserisci il tuo "tablename" (senza schema-prefisso) in SQL).
alfonx,

2
+1: questa è l'unica soluzione che non restituisce duplicati.
Olivier MATROT,

a questa soluzione, funziona bene e non restituisce duplicati.
Fuhrmann,

1
Questa soluzione mostrerà solo la prima colonna di qualsiasi chiave esterna multi-colonna ... ma sembra molto più semplice di quella che ho appena pubblicato che farà multipli.
Dewin,

12

Questa query funziona correttamente anche con chiavi composite:

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

2
Stai unendo le colonne su "nome_controllo", quindi funzionerà solo se tutti i nomi dei tuoi vincoli sono univoci (su tutte le tabelle in tutti gli schemi). Questo di solito non è un requisito e quindi non applicato dal database.
Zilk,

3
Grazie. Questa è l'unica risposta che mostra come utilizzare information_schema per gestire correttamente più colonne.
Samuel Danielson

Questa soluzione funziona. Non produce duplicati e gestisce più campi nell'FK.
Igor,

9

Penso che quello che stavi cercando e molto vicino a ciò che @ollyc ha scritto sia questo:

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';

Questo elencherà tutte le tabelle che usano la tabella specificata come chiave esterna


9

breve ma dolce voto se funziona per te.

select  * from information_schema.key_column_usage where constraint_catalog=current_catalog and table_name='your_table_name' and position_in_unique_constraint notnull;

Ha funzionato a meraviglia mentre scrivo con PG 12.2
Jack Kinsella

5

Nessuna delle risposte esistenti mi ha dato risultati nella forma in cui li volevo davvero. Quindi ecco la mia (gigantesca) query per trovare informazioni su chiavi esterne.

Alcune note:

  • Le espressioni usate per generare from_colse to_colspotrebbero essere notevolmente semplificate su Postgres 9.4 e WITH ORDINALITYversioni successive usando piuttosto che l'hacking che utilizza la funzione finestra che sto usando.
  • Le stesse espressioni si basano sul pianificatore di query che non altera l'ordine di risultati restituito UNNEST. Non credo che lo farà, ma non ho chiavi esterne a più colonne nel mio set di dati con cui testare. L'aggiunta delle 9.4 bellezze elimina del tutto questa possibilità.
  • La query stessa richiede Postgres 9.0 o successivo (8.x non ha consentito ORDER BYnelle funzioni aggregate)
  • Sostituire STRING_AGGcon ARRAY_AGGse si desidera una matrice di colonne anziché una stringa separata da virgola.

-

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;

5

Un altro modo:

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
;


4

Utilizzare il nome della chiave primaria a cui fanno riferimento le chiavi e interrogare lo 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')

Qui "TABLE_NAME_pkey" è il nome della chiave primaria a cui fanno riferimento le chiavi esterne.


4

Ecco una soluzione di Andreas Joseph Krogh dalla mailing list di PostgreSQL: http://www.postgresql.org/message-id/200811072134.44750.andreak@officenet.no

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;

Questa soluzione gestisce le chiavi esterne che fanno riferimento a più colonne ed evita i duplicati (che alcune delle altre risposte non riescono a fare). L'unica cosa che ho cambiato sono stati i nomi delle variabili.

Ecco un esempio che restituisce tutte le employeecolonne che fanno riferimento alla permissiontabella:

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

4

Per espandere la risposta eccellente di Martin, ecco una query che ti consente di filtrare in base alla tabella padre e ti mostra il nome della tabella figlio con ciascuna tabella padre in modo da poter vedere tutte le tabelle / colonne dipendenti in base ai vincoli della chiave esterna in la tabella padre.

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%'       

1
La query nella risposta accettata aggiunge 1,2 secondi a una query ~ 0,03, la tua aggiunge solo 0,01, grazie!
AVProgrammer

3

Corretta soluzione al problema, utilizzando information_schema, lavorando con chiavi multi colonna, unendo correttamente colonne di nomi diversi in entrambe le tabelle e anche compatibile con 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: ci sono alcune differenze tra le implementazioni di potgresql e sqlserver information_schemache fanno sì che la risposta migliore dia risultati diversi sui due sistemi: uno mostra i nomi delle colonne per la tabella delle chiavi esterne e l'altro per la tabella delle chiavi primarie. Per questo motivo ho deciso di utilizzare invece la vista KEY_COLUMN_USAGE.


Lo schema informativo sembra la risposta giusta, ma in realtà vuoi le tabelle pg_catalog: pg_constraint ecc. Siamo stati morsi duramente da questo. se il tuo database ha una grande quantità di vincoli ci possono essere problemi di prestazioni ...
hajikelist

La condizione sopra attivata ORDINAL_POSITIONpuò produrre risultati errati quando l'ordine delle colonne in chiave esterna è diverso dall'ordine delle colonne nel vincolo univoco. Credo che si dovrebbe avere aderito su kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Aggiornamento : Inoltre, una chiave esterna può dipendere da un vincolo unico e, quindi penso che si dovrebbe rimuovere la pks.CONSTRAINT_TYPEcondizioni e può solo aderire rcalla kcu_primarydiretta
EASD

Ho fatto una risposta simile qui: 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

2

Ho scritto una soluzione che piace e usa frequentemente. Il codice è disponibile all'indirizzo http://code.google.com/p/pgutils/ . Vedi la vista pgutils.foreign_keys.

Sfortunatamente, l'output è troppo prolisso per essere incluso qui. Tuttavia, puoi provarlo su una versione pubblica del database qui, in questo modo:

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

Funziona almeno con 8.3. Prevedo di aggiornarlo, se necessario, nei prossimi mesi.

-Reece


1
Il collegamento al progetto ora è morto.
pimlottc,

@pimlottc: spostato su bitbucket.org/reece/pgutils . Grazie per averlo segnalato.
Reece,


0

Nota: non dimenticare l'ordine delle colonne durante la lettura delle colonne dei vincoli!

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)

0

Questo è quello che sto attualmente usando, elencherà una tabella ed è vincoli fkey [rimuove la clausola della tabella ed elencherà tutte le tabelle nel catalogo corrente]:

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')

0

il più veloce da verificare direttamente nella risposta bash basata interamente su questa risposta

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"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.