Testovací nastavení
Předpokládáte název omezení test_def_abc_id_fkey
, výchozí název vyplývající z vašeho nastavení v Postgres 11 nebo starším. Za zmínku však stojí, že výchozí názvy byly vylepšeny pro Postgres 12, kde stejné nastavení vede k test_def_abc_id_abc_id2_fkey
. Poznámky k vydání Postgres 12:
Viz:
db<>fiddle zde
Použijme tedy explicitní název test_def_abc_fkey
pro omezení FK, aby nedošlo k záměně:
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)
);
A že funguje v Postgres 9.5 - Postgres 12.
Dokonce i v Postgresu 9.3.
(Měl jsem mylný dojem, že jde o skutečné omezení bude vyžadováno.)
Odpověď
Vaše pozorování z dotazování na informační schéma platí:
SELECT *
FROM information_schema.referential_constraints
WHERE constraint_name = 'test_def_abc_fkey'; -- unequivocal name
Dostaneme řádek, ale tři pole unique_constraint_catalog
, unique_constraint_schema
a unique_constraint_name
jsou NULL
.
Vysvětlení se zdá jednoduché. Tyto sloupce popisují, jak to uvádí manuál:
Ale neexistuje žádný UNIQUE
omezení
, jen UNIQUE
index
. UNIQUE
omezení je implementováno pomocí UNIQUE
index v Postgresu. Omezení jsou definována standardem SQL, indexy jsou detaily implementace. Existují rozdíly, jako je ten, který jste objevili. Související:
Stejný test se skutečným UNIQUE
omezení zobrazuje data podle očekávání:
db<>fiddle zde
Zdá se tedy, že to dává smysl. Zejména proto, že informační schéma je také definován výborem pro standardy SQL a indexy nejsou standardizovány, pouze omezují. (Žádné indexové informace v zobrazeních informačního schématu.)
Vše jasné? Ne tak docela.
Nicméně
Existuje další zobrazení informačního schématu key_column_usage
. Jeho poslední sloupec je popsán jako:
Tučné důraz můj. Zde je pořadová pozice sloupce v indexu je přesto uveden:
SELECT *
FROM information_schema.key_column_usage
WHERE constraint_name = 'test_def_abc_fkey';
Viz:
db<>fiddle zde
Zdá se nekonzistentní.
A co je horší, příručka
tvrdí, že skutečný PRIMARY KEY
nebo UNIQUE
omezení by bylo vyžadováno pro vytvoření FOREIGN KEY
omezení:
Zdá se, že jde o chybu v dokumentaci ? Pokud zde nikdo nemůže upozornit, kde dělám chybu, podám hlášení o chybě.
Související:
Řešení
V Postgresu je systémový katalog skutečným zdrojem pravdy. Viz:
Takže byste mohli použít něco takového (jako jsem také přidal do housle výše):
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';
Vrátí:
conname | fk_table | fk_columns | ref_table | ref_key_columns :---------------- | :------- | :--------------- | :-------- | :-------------- test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc | {id,id2}
Související:
- Najděte název odkazované tabulky pomocí názvu tabulky, pole a schématu
- Najít odkazované pole( s) omezení cizího klíče
- Jak najdu tabulky, které odkazují na konkrétní řádek prostřednictvím cizího klíče?