Testaufbau
Sie nehmen den Constraint-Namen test_def_abc_id_fkey
an , der Standardname, der sich aus Ihrer Einrichtung in Postgres 11 oder älter ergibt. Erwähnenswert ist jedoch, dass die Standardnamen für Postgres 12 verbessert wurden, wo dieselbe Einrichtung zu test_def_abc_id_abc_id2_fkey
führt . Die Versionshinweise für Postgres 12:
Siehe:
db<>fiddle hier
Verwenden wir also den expliziten Namen test_def_abc_fkey
für die FK-Einschränkung, um Verwirrung zu vermeiden:
CREATE TABLE test_abc (
pk int PRIMARY KEY
, id int NOT NULL
, id2 int NOT NULL
);
CREATE UNIQUE INDEX test_abc_ids ON test_abc(id,id2);
CREATE TABLE test_def (
id int PRIMARY KEY
, abc_id int
, abc_id2 int
, CONSTRAINT test_def_abc_fkey -- !
FOREIGN KEY (abc_id,abc_id2) REFERENCES test_abc(id,id2)
);
Und das funktioniert in Postgres 9.5 - Postgres 12.
Sogar in Postgres 9.3.
(Ich hatte den falschen Eindruck einer tatsächlichen Einschränkung erforderlich.)
Antwort
Ihre Beobachtung aus der Abfrage des Informationsschemas gilt:
SELECT *
FROM information_schema.referential_constraints
WHERE constraint_name = 'test_def_abc_fkey'; -- unequivocal name
Wir erhalten eine Zeile, aber die drei Felder unique_constraint_catalog
, unique_constraint_schema
und unique_constraint_name
sind NULL
.
Die Erklärung scheint einfach. Diese Spalten beschreiben, wie es im Handbuch heißt:
Aber es gibt keinen UNIQUE
Einschränkung
, nur ein UNIQUE
Index
. Ein UNIQUE
Einschränkung wird mit einem UNIQUE
implementiert Index in Postgres. Einschränkungen werden vom SQL-Standard definiert, Indizes sind Implementierungsdetails. Es gibt Unterschiede wie den, den Sie entdeckt haben. Verwandte:
Derselbe Test mit einem tatsächlichen UNIQUE
Einschränkung zeigt Daten wie erwartet:
db<>fiddle hier
Das scheint also Sinn zu machen. Vor allem seit dem Informationsschema wird auch vom SQL Standards Committee definiert und Indizes sind nicht standardisiert, sondern nur Einschränkungen. (Keine Indexinformationen in Informationsschemaansichten.)
Alles klar? Nicht ganz.
Allerdings
Es gibt eine weitere Ansicht des Informationsschemas key_column_usage
. Seine letzte Spalte wird wie folgt beschrieben:
Fett Betonung von mir. Hier die Ordinalposition der Spalte im Index wird trotzdem aufgelistet:
SELECT *
FROM information_schema.key_column_usage
WHERE constraint_name = 'test_def_abc_fkey';
Siehe:
db<>fiddle hier
Scheint widersprüchlich.
Was noch schlimmer ist, das Handbuch
behauptet, dass ein tatsächlicher PRIMARY KEY
oder UNIQUE
Einschränkung wäre für die Erstellung eines FOREIGN KEY
erforderlich Einschränkung:
Scheint ein Dokumentationsfehler zu sein ? Wenn niemand darauf hinweisen kann, wo ich hier falsch liege, werde ich einen Fehlerbericht einreichen.
Verwandte:
Lösung
In Postgres ist der Systemkatalog die eigentliche Quelle der Wahrheit. Siehe:
Sie könnten also so etwas verwenden (wie ich es auch in der Fiddle hinzugefügt habe oben):
SELECT c.conname
, c.conrelid::regclass AS fk_table, k1.fk_columns
, c.confrelid::regclass AS ref_table, k2.ref_key_columns
FROM pg_catalog.pg_constraint c
LEFT JOIN LATERAL (
SELECT ARRAY (
SELECT a.attname
FROM pg_catalog.pg_attribute a
, unnest(c.conkey) WITH ORDINALITY AS k(attnum, ord)
WHERE a.attrelid = c.conrelid
AND a.attnum = k.attnum
ORDER BY k.ord
) AS fk_columns
) k1 ON true
LEFT JOIN LATERAL (
SELECT ARRAY (
SELECT a.attname
FROM pg_catalog.pg_attribute a
, unnest(c.confkey) WITH ORDINALITY AS k(attnum, ord)
WHERE a.attrelid = c.confrelid
AND a.attnum = k.attnum
ORDER BY k.ord
) AS ref_key_columns
) k2 ON true
WHERE conname = 'test_def_abc_fkey';
Rückgabe:
conname | fk_table | fk_columns | ref_table | ref_key_columns :---------------- | :------- | :--------------- | :-------- | :-------------- test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc | {id,id2}
Verwandte:
- Suchen Sie den referenzierten Tabellennamen anhand des Tabellen-, Feld- und Schemanamens
- Find referenced field( s) der Fremdschlüsseleinschränkung
- Wie finde ich Tabellen, die über einen Fremdschlüssel auf eine bestimmte Zeile verweisen?