PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

NULL стойности за колони referential_constraints.unique_constraint_* в информационната схема

Тестова настройка

Вие приемате името на ограничението 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}       

Свързани:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Кавичките са неправилни при използване на crosstab() в PostgreSQL

  2. JOIN на ниво приложение с WHERE и ORDER BY на N postgresql шарда

  3. Аритметика на колоната за дата в заявката на PostgreSQL

  4. Сканиране на индекс за сравнение в няколко колони - неравномерно подреждане на колони на индекси

  5. Заявка към PostgreSQL с Npgsql и Entity Framework, използвайки неакцент