Like @lad2025 heeft gereageerd , status
zou echt boolean
moeten zijn
. Goedkoper, schoner.
Hoe dan ook, je kunt je regel opleggen met een gedeeltelijk unieke index :
Om nul of één rij toe te staan met status = 'Active'
in de hele tabel :
CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';
Om nul of één rij toe te staan met status = 'Active'
per userid
, maak userid
de geïndexeerde kolom:
CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';
Merk op dat userid IS NULL
zou geen unieke schendingen veroorzaken, omdat twee NULL-waarden nooit als gelijk worden beschouwd. userid
moet set NOT NULL
zijn
in dit geval.
- Een voorwaardelijke unieke index toevoegen aan PostgreSQL
- Maak een unieke beperking met null-kolommen
Waarom indexeren en niet beperken?
Het adresseren van uw vraag in de reactie
:Dit is een index, geen CONSTRAINT
.
De index voor het eerste geval is klein , met één of geen rij.
De index voor het tweede geval bevat één rij per bestaande userid
, maar het is de goedkoopste en snelste manier , naast schoon en veilig te zijn. Je zou in ieder geval een index nodig hebben om andere rijen te controleren om dit snel te maken.
U kunt geen CHECK
. hebben beperkingscontrole op andere rijen - in ieder geval niet op een schone, betrouwbare manier. Er zijn manieren die ik zeker niet zou aanraden voor dit geval:
- Trigger vs. controlebeperking
- Hoe vermijd ik een cyclische afhankelijkheid (circulaire verwijzing) tussen 3 tabellen?
- Schakel alle beperkingen en tabelcontroles uit tijdens het herstellen van een dump
Als u een UNIQUE
. gebruikt beperking op (userid, status)
(die ook is geïmplementeerd met een unieke index op de achtergrond!), je kunt het niet gedeeltelijk maken , en alle combinaties worden afgedwongen om uniek te zijn. Je zou gebruik dit nog steeds als u werkt met status IS NULL
voor alle gevallen behalve de 'Active'
geval. Maar dat zou eigenlijk een veel grotere index opleggen, inclusief alle rijen.