Gilla @ladd /a> , status
borde verkligen vara boolean
. Billigare, renare.
Hur som helst kan du införa din regel med ett partiellt unikt index :
För att tillåta noll eller en rad med status = 'Active'
i hela tabellen :
CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';
För att tillåta noll eller en rad med status = 'Active'
per userid
, gör userid
den indexerade kolumnen:
CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';
Observera att userid IS NULL
skulle inte utlösa unika överträdelser, eftersom två NULL-värden aldrig anses vara lika. userid
måste ställas in NOT NULL
i det här fallet.
- Hur man lägger till ett villkorligt unikt index på PostgreSQL
- Skapa unika restriktioner med nollkolumner
Varför indexera och inte begränsa?
Adressera din CONSTRAINT
.
Indexet för det första fallet är litet , med en eller ingen rad.
Indexet för det andra fallet innehåller en rad per befintligt userid
, men det är det billigaste och snabbaste sättet , förutom att vara ren och säker. Du skulle behöva ett index för att kontrollera andra rader i alla fall för att göra detta snabbt.
Du kan inte ha en CHECK
begränsningskontroll på andra rader - åtminstone inte på ett rent och tillförlitligt sätt. Det finns sätt jag absolut inte skulle rekommendera för det här fallet:
- Trigger vs. kontrollbegränsning
- Hur undviker man ett cykliskt beroende (cirkulär referens) mellan tre tabeller?
- Inaktivera alla begränsningar och tabellkontroller medan du återställer en dump
Om du använder en UNIQUE
begränsning på (userid, status)
(som också är implementerat med ett unikt index i bakgrunden!), du kan inte göra det partiellt och alla kombinationer tvingas vara unika. Du kunde använd fortfarande detta om du arbetar med status IS NULL
för alla fall utom 'Active'
fall. Men det skulle faktiskt påtvinga ett mycket större index inklusive alla rader.