Créer deux index partiels :
CREATE UNIQUE INDEX favo_3col_uni_idx ON favorites (user_id, menu_id, recipe_id)
WHERE menu_id IS NOT NULL;
CREATE UNIQUE INDEX favo_2col_uni_idx ON favorites (user_id, recipe_id)
WHERE menu_id IS NULL;
De cette façon, il ne peut y avoir qu'une seule combinaison de (user_id, recipe_id)
où menu_id IS NULL
, implémentant efficacement la contrainte souhaitée.
Inconvénients possibles :
- Vous ne pouvez pas avoir de clé étrangère référençant
(user_id, menu_id, recipe_id)
. (Il semble peu probable que vous vouliez une référence FK large de trois colonnes - utilisez plutôt la colonne PK !) - Vous ne pouvez pas baser
CLUSTER
sur un index partiel. - Requêtes sans
WHERE
correspondant la condition ne peut pas utiliser l'index partiel.
Si vous avez besoin d'un complet index, vous pouvez également déposer le WHERE
état de favo_3col_uni_idx
et vos exigences sont toujours appliquées.
L'index, qui comprend maintenant toute la table, chevauche l'autre et s'agrandit. En fonction des requêtes typiques et du pourcentage de NULL
valeurs, cela peut être utile ou non. Dans des situations extrêmes, il peut même être utile de maintenir les trois index (les deux partiels et un total en haut).
C'est une bonne solution pour une colonne nullable unique , peut-être pour deux. Mais cela devient rapidement incontrôlable car vous avez besoin d'un index partiel séparé pour chaque combinaison de colonnes nullables, de sorte que le nombre augmente de manière binomiale. Pour plusieurs colonnes nullables , voyez plutôt :
- Pourquoi ma contrainte UNIQUE ne se déclenche-t-elle pas ?
A part :je conseille de ne pas utiliser d'identifiants à casse mixte dans PostgreSQL.