Postgres: SQL zum Auflisten von Tabellenfremdschlüsseln


219

Gibt es eine Möglichkeit, mit SQL alle Fremdschlüssel für eine bestimmte Tabelle aufzulisten? Ich kenne den Tabellennamen / das Schema und kann das einstecken.


Ich schlage vor, die Antwort von @Magnus zu verwenden . Einfachste, sauberste, schnellste.
Erwin Brandstetter

Antworten:


373

Sie können dies über die Tabellen information_schema tun. Beispielsweise:

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' sollte tc.table_name = 'mytable' sein, sonst wird ein mehrdeutiger Fehler
ausgegeben

15
+1, sehr hilfreich. Um die Abfrage robuster zu machen, sollte sie wahrscheinlich auch mit dem Einschränkungsschema verknüpft werden, da es möglich ist, dass zwei Schemas Einschränkungen mit demselben Namen haben. So etwas wie: 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
Dies bricht ab, wenn eine Einschränkung mehrere Spalten enthält, nicht wahr? Es scheint keine richtige Möglichkeit zu geben, pk-Spalten fk-Spalten mithilfe von information_schema BTW zuzuordnen.
Fionbio

5
Es bricht tatsächlich mit mehr als einer Spalte in der Einschränkung. Für Postgres gibt es eine Möglichkeit, diese Informationen aus dem Schema pg_catalog abzurufen. Siehe meine Antwort unten.
Martin

9
Die Abfrage ist falsch. Es wird davon ausgegangen, dass Einschränkungsnamen nicht wiederholt werden können, was falsch ist. Einschränkungen mit demselben Namen können in verschiedenen Namespaces vorhanden sein. Sie verwenden Constraint_Name, um den Join herzustellen. Auch das Verknüpfen von Constraint_Name und Schemaname funktioniert nicht, da Sie nicht sicher sind, ob die beiden Constraints identisch sind. Die einzige Option besteht darin, pg_constraints, pg_class usw. mit oids zu verbinden. Der ANSI-Katalog von Postgres dient nur der Einhaltung, ist jedoch fehlerhaft. pg_catalog ist der richtige Weg. Die richtige Antwort ist hier dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova

69

psql macht das und wenn Sie psql starten mit:

psql -E

Es zeigt Ihnen genau, welche Abfrage ausgeführt wird. Wenn Sie Fremdschlüssel finden, ist dies:

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 diesem Fall ist 16485 die Oid der Tabelle, die ich betrachte. Sie können diese erhalten, indem Sie einfach Ihren Tabellennamen in eine neue Klasse umwandeln:

WHERE r.conrelid = 'mytable'::regclass

Schema-qualifizieren Sie den Tabellennamen, wenn er nicht eindeutig ist (oder der erste in Ihrem search_path):

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

2
Das ist sehr praktisch! Postgres scheint eine Million solcher kleinen Funktionen zu haben, die alles einfacher machen. Wie kann man sich an sie erinnern?
epic_fil

5
@Phil: Du brauchst nur eine allgemeine Idee. Lassen Sie das Handbuch den Rest merken.
Erwin Brandstetter

3
SELECT conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.confrelid = 'myschema.mytable'::regclass;
Um

1
@ErwinBrandstetter Wie mache ich einen fremden Tabellennamen?
Wellington Silva Ribeiro

2
Ich verstehe es nicht, welcher Befehl sollte verwendet werden? psql -E -U username -d database ThenWHAT?
Poutrathor

49

Problem \d+ tablenamebei der PostgreSQL-Eingabeaufforderung Zusätzlich zur Anzeige der Datentypen der Tabellenspalte werden die Indizes und Fremdschlüssel angezeigt.


Entschuldigung, ich habe nicht bemerkt, dass mein Kommentar abgeschnitten wurde. Wenn Sie es mindestens einmal versuchen könnten, würden auch die Fremdschlüsselzuordnungen angezeigt.
Gre Hahn

45

Ollycs Antwort ist gut, da sie nicht Postgres-spezifisch ist. Sie bricht jedoch zusammen, wenn der Fremdschlüssel auf mehr als eine Spalte verweist. Die folgende Abfrage funktioniert für eine beliebige Anzahl von Spalten, hängt jedoch stark von Postgres-Erweiterungen ab:

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

vor 8.4 muss zunächst die Funktion unnest erstellt werden. wiki.postgresql.org/wiki/Array_Unnest
Maletin

Wo fügt man den Tabellennamen in diese Abfrage ein? Wörtlich eingegeben, gibt das oben Gesagte 0 Zeilen in meiner PSQL-Datenbank zurück, die zehn Fremdschlüssel enthält.
Phrogz

4
Sie ersetzen 'child_table' und 'child_schema' durch die Namen der Tabelle und ihres Schemas
martin

das sagt dir nicht den Namen des fkey.
Evan Carroll

@EvanCarroll Ich habe meine Antwort aktualisiert und den Namen des Schlüssels angegeben.
Martin

31

Erweiterung des Ollyc-Rezepts:

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

Dann:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';;


Danke, ideal für die Wiederverwendung.
schellingerht

16

Überprüfen Sie den ff-Beitrag auf Ihre Lösung und vergessen Sie nicht, dies zu markieren, wenn Sie dies hilfreich finden

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

Bietet zwei SQLs, die unter PostgreSQL 9.1 funktionieren (sobald Sie das falsche Escapezeichen korrigiert haben, geben Sie Ihren 'Tabellennamen' (ohne Schema-Präfix) in das SQL ein).
Alfonx

2
+1: Dies ist die einzige Lösung, die keine Duplikate zurückgibt.
Olivier MATROT

funktioniert mit dieser Lösung einwandfrei und gibt keine Duplikate zurück.
Fuhrmann

1
Diese Lösung zeigt nur die erste Spalte eines mehrspaltigen Fremdschlüssels an ... sieht aber so viel einfacher aus als die, die ich gerade gepostet habe und die Vielfache ausführt.
Dewin

12

Diese Abfrage funktioniert auch mit zusammengesetzten Schlüsseln korrekt:

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
Sie verbinden die Spalten unter "Einschränkungsname". Dies funktioniert also nur, wenn alle Ihre Einschränkungsnamen eindeutig sind (über alle Tabellen in allen Schemas hinweg). Dies ist normalerweise keine Anforderung und wird daher von der Datenbank nicht erzwungen.
Zilk

3
Vielen Dank. Dies ist die einzige Antwort, die zeigt, wie mit information_schema mehrere Spalten richtig behandelt werden.
Samuel Danielson

Diese Lösung funktioniert. Es werden keine Duplikate erstellt und mehrere Felder in der FK verarbeitet.
Igor

9

Ich denke, was Sie gesucht haben und sehr nah an dem, was @ollyc geschrieben hat, ist Folgendes:

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

Dadurch werden alle Tabellen aufgelistet, die Ihre angegebene Tabelle als Fremdschlüssel verwenden


9

kurze aber süße Gegenstimme, wenn es für Sie funktioniert.

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

Hat einen Zauber gewirkt, als ich mit PG 12.2
Jack Kinsella

5

Keine der vorhandenen Antworten gab mir Ergebnisse in der Form, in der ich sie eigentlich haben wollte. Hier ist meine (gigantische) Abfrage, um Informationen über Fremdschlüssel zu finden.

Ein paar Anmerkungen:

  • Die Ausdrücke, die zum Generieren verwendet wurden from_colsund to_colsin Postgres 9.4 und höher erheblich vereinfacht werden könnten, verwenden WITH ORDINALITYnicht das von mir verwendete Fensterfunktions-Hackery.
  • Dieselben Ausdrücke basieren darauf, dass der Abfrageplaner die zurückgegebene Reihenfolge der Ergebnisse von nicht ändert UNNEST. Ich glaube nicht, dass dies der Fall sein wird, aber ich habe keine mehrspaltigen Fremdschlüssel in meinem Datensatz, mit denen ich testen kann. Das Hinzufügen der 9,4-Feinheiten schließt diese Möglichkeit insgesamt aus.
  • Die Abfrage selbst erfordert Postgres 9.0 oder höher (8.x hat keine ORDER BYaggregierten Funktionen zugelassen).
  • Ersetzen Sie STRING_AGGdurch, ARRAY_AGGwenn Sie ein Array von Spalten anstelle einer durch Kommas getrennten Zeichenfolge möchten.

- -

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

Ein anderer Weg:

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

Verwenden Sie den Namen des Primärschlüssels, auf den sich die Schlüssel beziehen, und fragen Sie das Informationsschema ab:

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

Hier ist 'TABLE_NAME_pkey' der Name des Primärschlüssels, auf den die Fremdschlüssel verweisen.


4

Hier ist eine Lösung von Andreas Joseph Krogh aus der PostgreSQL-Mailingliste: 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;

Diese Lösung verarbeitet Fremdschlüssel, die auf mehrere Spalten verweisen, und vermeidet Duplikate (was bei einigen anderen Antworten nicht der Fall ist). Das einzige, was ich geändert habe, waren die Variablennamen.

Hier ist ein Beispiel, das alle employeeSpalten zurückgibt , die auf die permissionTabelle verweisen :

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

4

Um Martins hervorragende Antwort zu erweitern, finden Sie hier eine Abfrage, mit der Sie basierend auf der übergeordneten Tabelle filtern und den Namen der untergeordneten Tabelle für jede übergeordnete Tabelle anzeigen können, damit Sie alle abhängigen Tabellen / Spalten basierend auf den Fremdschlüsseleinschränkungen in sehen können die übergeordnete Tabelle.

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
Die Abfrage in der akzeptierten Antwort fügt einer ~ 0,03-Abfrage 1,2 Sekunden hinzu, Ihre Abfrage fügt nur 0,01 hinzu, danke!
AVProgrammer

3

Richtige Lösung des Problems: Verwenden information_schema, Arbeiten mit mehrspaltigen Schlüsseln, korrektes Verknüpfen von Spalten mit unterschiedlichen Namen in beiden Tabellen und Kompatibilität mit 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

Hinweis: Es gibt einige Unterschiede zwischen Potgresql- und SQLServer-Implementierungen, bei information_schemadenen die Top-Antwort auf beiden Systemen unterschiedliche Ergebnisse liefert - einer zeigt die Spaltennamen für die Fremdschlüsseltabelle, der andere für die Primärschlüsseltabelle. Aus diesem Grund habe ich mich stattdessen für die Ansicht KEY_COLUMN_USAGE entschieden.


Das Informationsschema scheint die richtige Antwort zu sein, aber Sie möchten wirklich die pg_catalog-Tabellen: pg_constraint usw. Wir wurden davon hart gebissen. Wenn Ihre Datenbank große Einschränkungen aufweist, kann es zu Leistungsproblemen kommen ...
Hajikelist

Die obige Bedingung ORDINAL_POSITIONkann zu einem falschen Ergebnis führen, wenn sich die Reihenfolge der Spalten im Fremdschlüssel von der Reihenfolge der Spalten in der eindeutigen Einschränkung unterscheidet. Ich glaube , Sie beigetreten sind , sollten kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION aktualisieren : Auch ein Fremdschlüssel als auch auf einem UNIQUE - Einschränkung abhängen kann, so dass ich denke , Sie entfernen sollten pks.CONSTRAINT_TYPEZustand und nur anschließen kann , rcum kcu_primarydirekt
EASD

Ich habe hier eine ähnliche Antwort gegeben: 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

Ich habe eine Lösung geschrieben, die ich mag und häufig benutze. Der Code befindet sich unter http://code.google.com/p/pgutils/ . Siehe die Ansicht pgutils.foreign_keys.

Leider ist die Ausgabe zu wortreich, um sie hier aufzunehmen. Sie können es jedoch hier in einer öffentlichen Version der Datenbank wie folgt ausprobieren:

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

Dies funktioniert mindestens mit 8.3. Ich erwarte, es bei Bedarf in den nächsten Monaten zu aktualisieren.

-Reece


1
Der Projektlink ist jetzt tot.
Pimlottc

@pimlottc: Auf bitbucket.org/reece/pgutils verschoben . Vielen Dank für den Hinweis.
Reece

1

Ich habe ein kleines Tool erstellt, um das Datenbankschema abzufragen und dann zu vergleichen: Dump PostgreSQL- Datenbankschema mit Text

Es gibt Informationen über FK, aber die ollyc-Antwort enthält weitere Details.


0

Hinweis: Vergessen Sie beim Lesen von Einschränkungsspalten nicht die Reihenfolge der Spalten!

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

Dies ist, was ich derzeit verwende, es wird eine Tabelle und ihre fkey-Einschränkungen auflisten [Tabellenklausel entfernen und alle Tabellen im aktuellen Katalog auflisten]:

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

Die am schnellsten zu überprüfende Bash-Antwort, die vollständig auf dieser Antwort basiert

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"
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.