Различия между MATCH FULL, MATCH SIMPLE и MATCH PARTIAL?

29

Я заметил MATCH SIMPLEи MATCH FULL, но я не понимаю, что они делают. Я вижу, по умолчанию это MATCH SIMPLE; но как другие MATCHпредложения к FOREIGN KEYфункции ограничения?

Эван Кэрролл
источник

Ответы:

38

Проверьте CREATE TABLEстраницу руководства :

Есть три типа соответствия: MATCH FULL, MATCH PARTIALи MATCH SIMPLE (это значение по умолчанию). MATCH FULLне допустит, чтобы один столбец внешнего ключа из нескольких столбцов был нулевым, если все столбцы внешнего ключа не равны нулю; если все они являются нулевыми, строка не обязательно должна иметь совпадение в ссылочной таблице. MATCH SIMPLEпозволяет любому из столбцов внешнего ключа быть нулевым; если какой-либо из них имеет значение null, строка не обязательно должна иметь совпадение в ссылочной таблице. MATCH PARTIALеще не реализовано. (Конечно, NOT NULLограничения могут быть применены к ссылочному столбцу (столбцам), чтобы предотвратить возникновение этих случаев.)

Также в главе об иностранных ключах :

Обычно ссылочная строка не должна удовлетворять ограничению внешнего ключа, если какой-либо из ее столбцов ссылается на NULL. Если MATCH FULL он добавлен в объявление внешнего ключа, ссылочная строка выходит за пределы, удовлетворяющие ограничению, только в том случае, если все ее ссылочные столбцы имеют нулевое значение (поэтому сочетание нулевых и ненулевых значений гарантированно не выполнит MATCH FULL ограничение). Если вы не хотите, чтобы ссылки на строки могли избежать ограничения внешнего ключа, объявите столбец (и) ссылки как NOT NULL.

И обязательно ознакомьтесь с текущим руководством или версией, соответствующей вашей установке. Не поддавайтесь на устаревшие ссылки Google на устаревшие версии.

Эрвин Брандштеттер
источник
7

FULLпротив SIMPLEпротивPARTIAL

Несмотря на то, что выбранный ответ является правильным, если он для вас новый, вы можете захотеть увидеть его с помощью кода - я думаю, что так будет проще.

-- one row with (1,1)
CREATE TABLE foo ( a int, b int,
  PRIMARY KEY (a,b)
);
INSERT INTO foo (a,b) VALUES (1,1);

--
-- two child tables to reference it
-- 
CREATE TABLE t_full ( a int, b int,
  FOREIGN KEY (a,b) REFERENCES foo MATCH FULL
);
CREATE TABLE t_simple ( a int, b int,
  FOREIGN KEY (a,b) REFERENCES foo MATCH SIMPLE
);

Логически, с помощью FULLи SIMPLEмы можем вставить полное совпадение.

-- works
INSERT INTO t_full (a,b) VALUES (1,1);
INSERT INTO t_simple (a,b) VALUES (1,1);

Проблема возникает, когда один из столбцов есть NULL.

-- works
INSERT INTO t_simple (a,b) VALUES (1,NULL);

-- fails
INSERT INTO t_full (a,b) VALUES (1,NULL);

Вставка в t_fullгенерирует следующую ошибку,

ERROR:  insert or update on table "t_full" violates foreign key constraint "t_full_a_fkey"
DETAIL:  MATCH FULL does not allow mixing of null and nonnull key values.
INSERT 0 1

Хорошо, так что насчет (42,NULL)этой части, которая меня всегда смущала MATCH SIMPLE,

-- works
INSERT INTO t_simple (a,b) VALUES (42,NULL);

Такое поведение будет НЕ работать с нереализованным MATCH PARTIAL, что, вероятно, делает то, что вы хотите для составного индекса, где NULLвычеркнут крайний правый столбец . Тем не менее, некоторые люди рассматривают это как способ открыть ящик Пандоры для плохого дизайна.

Простые определения и мнемоника

  • MATCH FULLвсе должно полностью совпадать, или все столбцы должны бытьNULL
  • MATCH SIMPLEесли одна вещь является NULLограничением просто игнорируется.
  • MATCH PARTIALесли одна вещь NULLв том , что не все NULLэто частично спасенных делать что - то осмысленное с целью ограничения.

Замечания по спецификациям SQL

Для потомков, вот определения из спецификации SQL на <match type>

  • MATCH SIMPLEесли хотя бы один ссылающийся столбец имеет значение null, то строка таблицы ссылок проходит проверку ограничения. Если все ссылочные столбцы не равны NULL, тогда строка проходит проверку ограничения, если и только если есть строка таблицы, на которую ссылаются, которая соответствует всем ссылочным столбцам.
  • MATCH PARTIAL: если все ссылающиеся столбцы являются нулевыми, то строка таблицы ссылок проходит проверку ограничения. Если хотя бы один ссылающийся столбец не является нулевым, тогда строка проходит проверку ограничения, если и только если существует строка таблицы, на которую ссылаются, которая соответствует всем ненулевым ссылочным столбцам.
  • MATCH FULL: если все ссылающиеся столбцы являются нулевыми, то строка таблицы ссылок проходит проверку ограничения. Если все ссылочные столбцы не равны NULL, тогда строка проходит проверку ограничения, если и только если есть строка таблицы, на которую ссылаются, которая соответствует всем ссылочным столбцам. Если какой-либо столбец ссылки имеет значение NULL, а другой столбец ссылается не NULL, то строка таблицы ссылок нарушает проверку ограничения.

Хотя это не является специфичным для PostgreSQL, эти примеры демонстрируются на PostgreSQL.

Эван Кэрролл
источник