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

Aggiungi vincolo per rendere la colonna univoca per gruppo di righe

Mi piace @lad2025 ha commentato , status dovrebbe essere davvero boolean . Più economico, più pulito.

In ogni caso, puoi imporre la tua regola con un indice univoco parziale :

Per consentire zero o una riga con status = 'Active' in tutta la tabella :

CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';

Per consentire zero o una riga con status = 'Active' per userid , crea userid la colonna indicizzata:

CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';

Nota che userid IS NULL non attiverebbe violazioni univoche, perché due valori NULL non sono mai considerati uguali. userid deve essere impostato NOT NULL in questo caso.

Perché indice e non vincolo?

Affrontare il tuo domanda nel commento :Questo è un indice, non un CONSTRAINT .

L'indice per il primo caso è minuscolo , con una o nessuna riga.
L'indice per il secondo caso contiene una riga per userid esistente , ma è il modo più economico e veloce , oltre ad essere pulito e sicuro. Avresti comunque bisogno di un indice per controllare altre righe per renderlo veloce.

Non puoi avere un CHECK controllo dei vincoli su altre righe, almeno non in modo pulito e affidabile. Ci sono modi che sicuramente non consiglierei per questo caso:

Se utilizzi un UNIQUE vincolo su (userid, status) (che è anche implementato con un indice univoco in background!), non puoi renderlo parziale e tutti le combinazioni sono obbligate a essere uniche. Potresti continua a usarlo se lavori con status IS NULL per tutti i casi tranne il 'Active' Astuccio. Ma ciò imporrebbe effettivamente un indice molto più grande che includa tutti righe.