Konfiguracja testowa
Przyjmujesz nazwę ograniczenia test_def_abc_id_fkey
, domyślna nazwa wynikająca z konfiguracji w Postgres 11 lub starszym. Warto jednak zauważyć, że domyślne nazwy zostały ulepszone w Postgres 12, gdzie ta sama konfiguracja daje wynik test_def_abc_id_abc_id2_fkey
. Informacje o wydaniu Postgresa 12:
Zobacz:
db<>fiddle tutaj
Użyjmy więc wyraźnej nazwy test_def_abc_fkey
dla ograniczenia FK, aby uniknąć nieporozumień:
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)
);
I to działa w Postgresie 9.5 – Postgresie 12.
Nawet w Postgresie 9.3.
(Miałem błędne wrażenie rzeczywistego ograniczenia byłoby wymagane).
Odpowiedź
Twoja obserwacja z zapytania o schemat informacji zawiera:
SELECT *
FROM information_schema.referential_constraints
WHERE constraint_name = 'test_def_abc_fkey'; -- unequivocal name
Otrzymujemy wiersz, ale trzy pola unique_constraint_catalog
, unikalny_schemat_ograniczeń
i unikalna_nazwa_ograniczenia
są NULL
.
Wyjaśnienie wydaje się proste. Te kolumny opisują, jak to ujmuje instrukcja:
Ale nie ma UNIQUE ograniczenie
, po prostu UNIKALNE
indeks
. UNIKALNY
ograniczenie jest implementowane przy użyciu UNIKALNEGO
indeks w Postgresie. Ograniczenia są zdefiniowane przez standard SQL, indeksy są szczegółami implementacji. Są różnice takie jak ta, którą odkryłeś. Powiązane:
Ten sam test z rzeczywistym UNIKALNYM
ograniczenie pokazuje dane zgodnie z oczekiwaniami:
db<>fiddle tutaj
Więc to wydaje się mieć sens. Zwłaszcza, że schemat informacyjny jest również definiowany przez komitet standardów SQL, a indeksy nie są ustandaryzowane, a jedynie ograniczenia. (Brak informacji o indeksie w widokach schematu informacji.)
Wszystko jasne? Niezupełnie.
Jednak
Istnieje inny widok schematu informacji key_column_usage
. Jego ostatnia kolumna jest opisana jako:
Pogrubienie mój nacisk. Tutaj pozycja porządkowa kolumny w indeksie i tak jest na liście:
SELECT *
FROM information_schema.key_column_usage
WHERE constraint_name = 'test_def_abc_fkey';
Zobacz:
db<>fiddle tutaj
Wydaje się niespójne.
Co gorsza, instrukcja
twierdzi, że rzeczywisty PRIMARY KEY
lub UNIKALNE
ograniczenie byłoby wymagane do utworzenia KLUCZA OBCEGO
ograniczenie:
Wygląda na błąd w dokumentacji ? Jeśli nikt nie będzie w stanie wskazać, co robię źle, zgłoszę błąd.
Powiązane:
Rozwiązanie
W Postgres katalog systemowy jest rzeczywistym źródłem prawdy. Zobacz:
Więc możesz użyć czegoś takiego (jak dodałem również w skrzypce powyżej):
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';
Zwroty:
conname | fk_table | fk_columns | ref_table | ref_key_columns :---------------- | :------- | :--------------- | :-------- | :-------------- test_def_abc_fkey | test_def | {abc_id,abc_id2} | test_abc | {id,id2}
Powiązane:
- Znajdź nazwę tabeli, do której istnieje odwołanie, używając nazwy tabeli, pola i schematu
- Znajdź pole odniesienia ( s) ograniczenia klucza obcego
- Jak znaleźć tabele, które odwołują się do określonego wiersza za pomocą klucza obcego?