Synes godt om @20 /a> , status
burde virkelig være boolean
. Billigere, renere.
Uanset hvad, kan du indføre din regel med et delvist unikt indeks :
At tillade nul eller én række med status = 'Active'
i hele tabellen :
CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';
At tillade nul eller én række med status = 'Active'
pr. userid
, lav userid
den indekserede kolonne:
CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';
Bemærk, at userid IS NULL
ville ikke udløse unikke overtrædelser, fordi to NULL-værdier aldrig betragtes som ens. userid
skal være sat NOT NULL
i dette tilfælde.
Hvorfor indeksere og ikke begrænsning?
Adressering af din CONSTRAINT
.
Indekset for det første tilfælde er lille , holder en eller ingen række.
Indekset for det andet tilfælde indeholder en række pr. eksisterende userid
, men det er den billigste og hurtigste måde , ud over at være rent og sikkert. Du skal under alle omstændigheder have et indeks for at kontrollere andre rækker for at gøre dette hurtigt.
Du kan ikke have en CHECK
begrænsningskontrol på andre rækker - i hvert fald ikke på en ren, pålidelig måde. Der er måder, jeg bestemt ikke vil anbefale for dette tilfælde:
- Trigger vs. kontrolbegrænsning
- Hvordan undgår man en cyklisk afhængighed (cirkulær reference) mellem 3 tabeller?
- Deaktiver alle begrænsninger og tabeltjek, mens du gendanner et dump
Hvis du bruger en UNIQUE
begrænsning på (userid, status)
(som også er implementeret med et unikt indeks i baggrunden!), du kan ikke gøre det delvis , og alle kombinationer tvinges til at være unikke. Du kunne brug stadig dette, hvis du arbejder med status IS NULL
for alle tilfælde undtagen 'Active'
sag. Men det ville faktisk påtvinge et meget større indeks inklusive alle rækker.