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:
- Trigger e vincolo di controllo
- Come evitare una dipendenza ciclica (riferimento circolare) tra 3 tabelle?
- Disabilita tutti i vincoli e i controlli delle tabelle durante il ripristino di un dump
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.