Contrainte de colonne unique personnalisée, appliquée uniquement si une colonne a une valeur spécifique


19

Est-il possible d'avoir une contrainte de colonne unique personnalisée comme suit? Supposons que j'ai deux colonnes subsetet les typedeux chaînes (bien que les types de données n'aient probablement pas d'importance).

Si typec'est "vrai", alors je veux que la combinaison de typeet subsetsoit unique. Sinon, il n'y a pas de contrainte. J'utilise PostgreSQL 8.4 sur Debian.


Réponses:


31

En d'autres termes, vous voulez subsetêtre unique si type = 'true'.
Un index unique partiel fera cela:

CREATE UNIQUE INDEX tbl_some_name_idx ON tbl (subset) WHERE type = 'true';

De cette façon, vous pouvez même créer des combinaisons avec NULLunique, ce qui n'est pas possible autrement - comme détaillé dans cette réponse connexe:
contrainte unique à plusieurs colonnes PostgreSQL et valeurs NULL


Merci Erwin. Je n'ai pas vu cette option lorsque j'ai regardé la documentation. Un lien plus direct est postgresql.org/docs/current/interactive/indexes-partial.html . Voir l'exemple 11-3.
Faheem Mitha

@FaheemMitha: J'ai lié un niveau plus haut, car vous devez combiner un index partiel avec un index unique .
Erwin Brandstetter

1
@Erwin Cette page (sur les index partiels), a un exemple avec un index unique partiel.
ypercubeᵀᴹ

@ypercube: Ah, c'est vrai. C'est le meilleur lien. J'ai changé ma réponse pour pointer vers ce dernier chapitre.
Erwin Brandstetter

6

Ceci est complémentaire à la réponse d'Erwin ci-dessus, mais PostgreSQL prend en charge un tas de types d'index. Ce ne sont généralement pas mutuellement exclusifs. Vous pouvez les considérer comme:

  • Méthode d'indexation (btree, GiST, GIN, etc.). Choisissez-en un, si nécessaire (btree étant la valeur par défaut)
  • Partielle ou complète. Si partiel, utilisez une clause where
  • Direct ou fonctionnel. Vous pouvez indexer la sortie des fonctions.
  • Unique ou non unique

Ceux-ci peuvent tous être combinés de différentes manières. Tout ce que vous faites ici est d'utiliser les fonctionnalités uniques et partielles, ce qui vous donne des index uniques partiels (qui sont extrêmement utiles lorsque vous le découvrez).

Mais supposons que vous vouliez avoir un index insensible à la casse sur le champ de sous-ensemble où le type est vrai. Ensuite, vous ajouteriez une définition fonctionnelle:

CREATE INDEX my_index_name_idx_u ON tbl (lower(subset)) WHERE type;

Notez que cela crée un index unique sur la sortie de la fonction lower () appelée sur l'attribut de sous-ensemble où type est true.


Donc, l'index dans la réponse d'Erwin est direct, alors que celui de votre exemple est fonctionnel, n'est-ce pas?
Faheem Mitha

@FaheemMitha: Correct.
Erwin Brandstetter
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.