Тестова настройка
Вие приемате името на ограничението test_def_abc_id_fkey
, името по подразбиране, произтичащо от вашата настройка в Postgres 11 или по-стара. Струва си да се отбележи обаче, че имената по подразбиране са подобрени за Postgres 12, където същата настройка води до test_def_abc_id_abc_id2_fkey
. Бележки за изданието за Postgres 12:
Вижте:
db<>fiddle тук
Така че нека използваме изричното име test_def_abc_fkey
за ограничението FK, за да избегнете объркване:
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)
);
И това работи в Postgres 9.5 - Postgres 12.
Дори в Postgres 9.3.
(Бях с погрешно впечатление за действително ограничение ще се изисква.)
Отговор
Вашето наблюдение от запитването на информационната схема е валидно:
SELECT *
FROM information_schema.referential_constraints
WHERE constraint_name = 'test_def_abc_fkey'; -- unequivocal name
Получаваме ред, но трите полета unique_constraint_catalog
, unique_constraint_schema
и unique_constraint_name
са NULL
.
Обяснението изглежда просто. Тези колони описват, както се казва в ръководството:
Но няма UNIQUEкод> ограничение
, просто УНИКАЛЕН
индекс
. УНИКАЛЕН
ограничението се прилага с помощта на UNIQUE
индекс в Postgres. Ограниченията са дефинирани от стандарта SQL, индексите са подробности за изпълнението. Има разлики като тази, която ти откри. Свързани:
Същият тест с действителен UNIQUE
ограничение показва данни според очакванията:
db<>fiddle тук
Така че това изглежда има смисъл. Особено след като информационната схема също се дефинира от комитета по стандартите на SQL и индексите не са стандартизирани, а само ограничения. (Няма индексна информация в изгледите на информационна схема.)
Всичко е ясно? Не съвсем.
Въпреки това
Има друг изглед на информационна схема key_column_usage
. Последната му колона е описана като:
Удебелен акцентът е мой. Тук поредната позиция на колоната в индекса все пак е в списъка:
SELECT *
FROM information_schema.key_column_usage
WHERE constraint_name = 'test_def_abc_fkey';
Вижте:
db<>fiddle тук
Изглежда непоследователно.
Което е по-лошо, ръководството
твърди, че действителен PRIMARY KEY
или УНИКАЛЕН
ограничение ще бъде необходимо за създаването на FOREIGN KEY
ограничение:
Изглежда, че е бъг в документацията ? Ако никой не може да посочи къде бъркам тук, ще подам доклад за грешка.
Свързани:
Решение
В Postgres системният каталог е действителният източник на истината. Вижте:
Така че бихте могли да използвате нещо подобно (както добавих и в цигулката по-горе):
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';
Връща:
conname | fk_table | fk_columns | ref_table | ref_key_columns :---------------- | :------- | :--------------- | :-------- | :-------------- test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc | {id,id2}
Свързани:
- Намерете името на референтната таблица, като използвате име на таблица, поле и схема
- Намиране на референтно поле( s) на ограничение за външен ключ
- Как мога да намеря таблици, които препращат към определен ред чрез външен ключ?