Diferenças entre MATCH FULL, MATCH SIMPLE e MATCH PARCIAL?

29

Eu notei um MATCH SIMPLEe MATCH FULL, mas não entendo o que eles fazem. Eu vejo o padrão é MATCH SIMPLE; mas, como as outras MATCHcláusulas da FOREIGN KEYrestrição funcionam?

Evan Carroll
fonte

Respostas:

38

Verifique a CREATE TABLEpágina do manual :

Existem três tipos de correspondência: MATCH FULL, MATCH PARTIALe MATCH SIMPLE (que é o padrão). MATCH FULLnão permitirá que uma coluna de uma chave estrangeira de várias colunas seja nula, a menos que todas as colunas de chave estrangeira sejam nulas; se forem todos nulos, não é necessário que a linha tenha uma correspondência na tabela referenciada. MATCH SIMPLEpermite que qualquer uma das colunas de chave estrangeira seja nula; se algum deles for nulo, não é necessário que a linha tenha uma correspondência na tabela referenciada. MATCH PARTIALainda não está implementado. (Obviamente, NOT NULLrestrições podem ser aplicadas às colunas de referência para impedir que esses casos ocorram.)

Além disso, no capítulo sobre Chaves estrangeiras :

Normalmente, uma linha de referência não precisa satisfazer a restrição de chave estrangeira se alguma de suas colunas de referência for nula. Se MATCH FULL for adicionado à declaração de chave estrangeira, uma linha de referência escapará satisfazendo a restrição apenas se todas as suas colunas de referência forem nulas (portanto, é garantido que uma combinação de valores nulos e não nulos falhará em uma MATCH FULL restrição). Se você não deseja que as linhas de referência evitem satisfazer a restrição de chave estrangeira, declare as colunas de referência como NOT NULL.

E não deixe de consultar o manual atual ou a versão correspondente à sua instalação. Não caia em links desatualizados do Google para versões desatualizadas.

Erwin Brandstetter
fonte
7

FULLvs SIMPLEvsPARTIAL

Embora a resposta escolhida esteja correta, se isso é novidade para você, você pode querer vê-la com código - acho que é mais fácil pensar dessa maneira.

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

Logicamente, com FULLe SIMPLE, podemos inserir uma correspondência completa.

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

O problema surge quando uma das colunas é NULL.

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

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

A inserção em t_fullgera o seguinte erro,

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, so what about (42,NULL) -- this is the part that I always found confusing about MATCH SIMPLE,

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

O comportamento acima NÃO funcionaria com os não implementados MATCH PARTIAL, o que provavelmente faz o que você deseja para um índice composto no qual a coluna mais à direita é NULLeditada. No entanto, algumas pessoas vêem isso como um método de abrir a caixa de uma Pandora para um design ruim.

Definições simples e mnemônicos

  • MATCH FULLtudo deve corresponder totalmente ou todas as colunas devem serNULL
  • MATCH SIMPLEse uma coisa é NULLa restrição é simplesmente ignorada.
  • MATCH PARTIALSe uma coisa é NULLo fato de que nem tudo está NULLé parcialmente recuperado fazendo algo sensato com a finalidade da restrição.

Notas de especificação SQL

Para a posteridade, aqui estão as definições do SQL Spec no diretório <match type>

  • MATCH SIMPLEse pelo menos uma coluna de referência for nula, a linha da tabela de referência passará na verificação de restrição. Se todas as colunas de referência não forem nulas, a linha passará na verificação de restrição se e somente se houver uma linha da tabela referenciada que corresponda a todas as colunas de referência.
  • MATCH PARTIAL: se todas as colunas de referência forem nulas, a linha da tabela de referência passará na verificação de restrição. Se pelo menos uma coluna de referência não for nula, a linha passará na verificação de restrição se e somente se houver uma linha da tabela referenciada que corresponda a todas as colunas de referência não nulas.
  • MATCH FULL: se todas as colunas de referência forem nulas, a linha da tabela de referência passará na verificação de restrição. Se todas as colunas de referência não forem nulas, a linha passará na verificação de restrição se e somente se houver uma linha da tabela referenciada que corresponda a todas as colunas de referência. Se alguma coluna de referência for nula e outra não for nula, a linha da tabela de referência violará a verificação de restrição.

Embora isso não seja específico do PostgreSQL, esses exemplos são demonstrados com o PostgreSQL

Evan Carroll
fonte