PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wartości NULL dla referential_constraints.unique_constraint_* kolumn w schemacie informacyjnym

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_ograniczeniaNULL .

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:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Porównaj wyniki dwóch funkcji tabel przy użyciu jednej kolumny z każdej

  2. Wywołanie procedury składowanej w ramach procedury składowanej

  3. Połącz się z postgresem w kontenerze docker z komputera hosta

  4. Dlaczego nowy użytkownik PostgreSQL może łączyć się ze wszystkimi bazami danych?

  5. Przechowywanie obrazów w polach bajtowych w bazie danych PostgreSQL