Różnice między MATCH FULL, MATCH SIMPLE i MATCH PARTIAL?

Odpowiedzi:

38

Sprawdź CREATE TABLEstronę instrukcji :

Istnieją trzy typy dopasowania: MATCH FULL, MATCH PARTIAL, oraz MATCH SIMPLE (co jest domyślne). MATCH FULLnie zezwoli na to, aby jedna kolumna klucza obcego wielokolumna była pusta, chyba że wszystkie kolumny klucza obcego są puste; jeśli wszystkie są puste, wiersz nie musi mieć dopasowania w tabeli, do której się odwołuje. MATCH SIMPLEpozwala, aby dowolna kolumna klucza obcego była pusta; jeśli którykolwiek z nich jest pusty, wiersz nie musi mieć dopasowania w tabeli, do której istnieje odwołanie. MATCH PARTIALnie jest jeszcze zaimplementowany. (Oczywiście, NOT NULLmożna zastosować ograniczenia do kolumn odniesienia, aby zapobiec powstawaniu takich przypadków.)

Ponadto w rozdziale dotyczącym kluczy obcych :

Zwykle wiersz odniesienia nie musi spełniać ograniczenia klucza obcego, jeśli którakolwiek z jego kolumn odniesienia ma wartość NULL. Jeśli MATCH FULL zostanie dodany do deklaracji klucza obcego, wiersz odniesienia ucieka spełniając ograniczenie tylko wtedy, gdy wszystkie jego kolumny odwołujące są puste (tak więc zagwarantowane jest, że połączenie wartości null i innych niż null nie spowoduje MATCH FULL ograniczenia). Jeśli nie chcesz, aby wiersze odniesienia mogły uniknąć spełnienia ograniczenia klucza obcego, zadeklaruj kolumny odniesienia jako NOT NULL.

I zapoznaj się z aktualną instrukcją lub wersją pasującą do twojej instalacji. Nie daj się nabrać na przestarzałe linki Google do nieaktualnych wersji.

Erwin Brandstetter
źródło
7

FULLvs SIMPLEvsPARTIAL

Chociaż wybrana odpowiedź jest prawidłowa, jeśli jest to dla Ciebie nowość, możesz chcieć zobaczyć ją z kodem - myślę, że łatwiej jest to zrobić.

-- 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
);

Logicznie, za pomocą FULLi SIMPLE, możemy wstawić pełne dopasowanie.

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

Problem pojawia się, gdy jedna z kolumn jest NULL.

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

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

Wstaw do t_fullgeneruje następujący błąd:

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

Ok, więc co z (42,NULL)- to część, którą zawsze uważałem za mylącą MATCH SIMPLE,

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

Powyższe zachowanie NIE działałoby w przypadku niezaimplementowanego MATCH PARTIAL, który prawdopodobnie robi to, co chcesz dla indeksu złożonego, w którym kolumna znajdująca się najbardziej na prawoNULL się wyłączona. Jednak niektórzy uważają to za metodę otwarcia pudełka Pandory na zły projekt.

Proste definicje i mnemoniki

  • MATCH FULLwszystko musi być w pełni zgodne lub wszystkie kolumny muszą byćNULL
  • MATCH SIMPLEjeśli jedno jest NULLto ograniczenie, jest po prostu ignorowane.
  • MATCH PARTIALjeśli jedno jest NULLfakt, że nie wszystko NULLjest częściowo uratowane przez robi coś sensownego dla celów ograniczeń.

Uwagi do specyfikacji SQL

Dla potomnych, oto definicje ze specyfikacji SQL na stronie <match type>

  • MATCH SIMPLEjeśli co najmniej jedna kolumna odniesienia ma wartość NULL, wówczas wiersz tabeli odniesienia przechodzi kontrolę ograniczenia. Jeśli wszystkie kolumny odwołań nie mają wartości NULL, wówczas wiersz przechodzi sprawdzenie ograniczenia wtedy i tylko wtedy, gdy istnieje wiersz tabeli, do której istnieją odwołania, która pasuje do wszystkich kolumn odniesienia.
  • MATCH PARTIAL: jeśli wszystkie kolumny odwołujące się mają wartość NULL, wówczas wiersz tabeli odwołującej przechodzi kontrolę ograniczenia. Jeśli co najmniej jedna kolumna odwołująca się nie ma wartości NULL, wówczas wiersz przechodzi sprawdzanie ograniczenia wtedy i tylko wtedy, gdy istnieje wiersz tabeli odwołującej się, który pasuje do wszystkich kolumn odwołujących się do wartości innej niż NULL.
  • MATCH FULL: jeśli wszystkie kolumny odwołujące się mają wartość NULL, wówczas wiersz tabeli odwołującej przechodzi kontrolę ograniczenia. Jeśli wszystkie kolumny odwołań nie mają wartości NULL, wówczas wiersz przechodzi sprawdzenie ograniczenia wtedy i tylko wtedy, gdy istnieje wiersz tabeli, do której istnieją odwołania, która pasuje do wszystkich kolumn odniesienia. Jeśli jakaś kolumna odniesienia ma wartość NULL, a inna kolumna odniesienia ma wartość inną niż NULL, wówczas wiersz tabeli odwołań narusza kontrolę ograniczenia.

Chociaż nie jest to specyficzne dla PostgreSQL, przykłady pokazano w PostgreSQL

Evan Carroll
źródło