Comme @lad2025 a commenté , status
devrait vraiment être boolean
. Moins cher, plus propre.
Dans tous les cas, vous pouvez imposer votre règle avec un index unique partiel :
Pour autoriser zéro ou une ligne avec status = 'Active'
dans tout le tableau :
CREATE UNIQUE INDEX tbl_active_uni ON tbl (status)
WHERE status = 'Active';
Pour autoriser zéro ou une ligne avec status = 'Active'
par userid
, créez userid
la colonne indexée :
CREATE UNIQUE INDEX tbl_userid_active_uni ON tbl (userid)
WHERE status = 'Active';
Notez que userid IS NULL
ne déclencherait pas de violations uniques, car deux valeurs NULL ne sont jamais considérées comme égales. userid
doit être set NOT NULL
dans ce cas.
- Comment ajouter un index unique conditionnel sur PostgreSQL
- Créer une contrainte unique avec des colonnes nulles
Pourquoi indexer et non contraindre ?
Répondre à votre question dans le commentaire
:Ceci est un index, pas une CONSTRAINT
.
L'indice pour le premier cas est minuscule , contenant une ou aucune ligne.
L'index du second cas contient une ligne par userid
existant , mais c'est le moyen le moins cher et le plus rapide , en plus d'être propre et sécuritaire. Vous auriez besoin d'un index pour vérifier les autres lignes dans tous les cas pour que cela soit rapide.
Vous ne pouvez pas avoir de CHECK
vérification des contraintes sur les autres lignes - du moins pas de manière propre et fiable. Il y a des façons que je ne recommanderais certainement pas pour ce cas :
- Trigger contre contrainte de vérification
- Comment éviter une dépendance cyclique (référence circulaire) entre 3 tables ?
- Désactiver toutes les contraintes et vérifications de table lors de la restauration d'un vidage
Si vous utilisez un UNIQUE
contrainte sur (userid, status)
(qui est également implémenté avec un index unique en arrière-plan !), vous ne pouvez pas le rendre partiel , et tous les combinaisons sont imposées pour être uniques. Vous pourriez utilisez toujours ceci si vous travaillez avec status IS NULL
pour tous les cas sauf 'Active'
Cas. Mais cela imposerait en fait un index beaucoup plus grand comprenant tous lignes.