PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Criar restrição exclusiva com colunas nulas


Crie dois índices parciais :
CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;

CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;

Dessa forma, só pode haver uma combinação de (user_id, recipe_id) onde menu_id IS NULL , implementando efetivamente a restrição desejada.

Possíveis desvantagens:
  • Você não pode ter uma chave estrangeira referenciando (user_id, menu_id, recipe_id) . (Parece improvável que você queira uma referência FK com três colunas de largura - use a coluna PK!)
  • Você não pode basear CLUSTER em um índice parcial.
  • Consultas sem um WHERE correspondente condição não pode usar o índice parcial.

Se você precisa de um completo index, você pode, alternativamente, soltar o WHERE condição de favo_3col_uni_idx e seus requisitos ainda são aplicados.
O índice, agora compreendendo toda a tabela, se sobrepõe ao outro e fica maior. Dependendo das consultas típicas e da porcentagem de NULL valores, isso pode ou não ser útil. Em situações extremas, pode até ajudar a manter os três índices (os dois parciais e um total no topo).

Esta é uma boa solução para uma coluna anulável única , talvez para dois. Mas fica fora de controle rapidamente para mais, pois você precisa de um índice parcial separado para cada combinação de colunas anuláveis, para que o número cresça binomialmente. Para várias colunas anuláveis , veja em vez disso:
  • Por que minha restrição UNIQUE não é acionada?

A parte:aconselho não usar identificadores de maiúsculas e minúsculas no PostgreSQL.