PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Crea un vincolo univoco con colonne nulle

Crea due indici parziali :

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;

In questo modo, può esserci solo una combinazione di (user_id, recipe_id) dove menu_id IS NULL , implementando efficacemente il vincolo desiderato.

Possibili inconvenienti:

  • Non puoi avere una chiave esterna che faccia riferimento a (user_id, menu_id, recipe_id) . (Sembra improbabile che tu voglia un riferimento FK largo tre colonne:usa invece la colonna PK!)
  • Non puoi basare CLUSTER su un indice parziale.
  • Query senza un WHERE corrispondente condizione non può utilizzare l'indice parziale.

Se hai bisogno di un completo index, in alternativa puoi rilasciare il WHERE condizione da favo_3col_uni_idx e i tuoi requisiti sono ancora applicati.
L'indice, che ora comprende l'intera tabella, si sovrappone all'altra e diventa più grande. A seconda delle query tipiche e della percentuale di NULL valori, questo può essere utile o meno. In situazioni estreme può anche aiutare a mantenere tutti e tre gli indici (i due parziali e un totale in alto).

Questa è una buona soluzione per una colonna nullable singola , forse per due. Ma sfugge rapidamente di mano per di più poiché è necessario un indice parziale separato per ogni combinazione di colonne nullable, quindi il numero cresce in modo binomiale. Per più colonne annullabili , vedi invece:

  • Perché il mio vincolo UNIQUE non si attiva?

A parte:consiglio di non utilizzare identificatori di casi misti in PostgreSQL.