PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Contrainte Postgres garantissant qu'une colonne parmi plusieurs est présente ?

Mise à jour du 17/09/2021  :À ce jour, gerardnll fournit une meilleure réponse (la meilleure IMO) :

Afin d'aider les gens à trouver la solution la plus propre, je vous recommande de voter pour la réponse de gerardnll .

(Pour votre information, je suis la même personne qui a posé la question initiale.)

Voici ma réponse originale de 2013

Voici une solution élégante à deux colonnes selon la "contrainte -- une ou l'autre colonne non nulle" Message Board PostgreSQL :

ALTER TABLE my_table ADD CONSTRAINT my_constraint CHECK (
  (column_1 IS NULL) != (column_2 IS NULL));

(Mais l'approche ci-dessus n'est pas généralisable à trois colonnes ou plus.)

Si vous avez trois colonnes ou plus, vous pouvez utiliser l'approche de la table de vérité illustrée par a_horse_with_no_name . Cependant, je considère que les éléments suivants sont plus faciles à gérer car vous n'avez pas à saisir les combinaisons logiques :

ALTER TABLE my_table
ADD CONSTRAINT my_constraint CHECK (
  (CASE WHEN column_1 IS NULL THEN 0 ELSE 1 END) +
  (CASE WHEN column_2 IS NULL THEN 0 ELSE 1 END) +
  (CASE WHEN column_3 IS NULL THEN 0 ELSE 1 END) = 1;

Pour compacter cela, il serait utile de créer une fonction personnalisée afin que le CASE WHEN column_k IS NULL THEN 0 ELSE 1 END le passe-partout pourrait être supprimé, laissant quelque chose comme :

(non_null_count(column_1) +
non_null_count(column_2) +
non_null_count(column_3)) = 1

Cela peut être aussi compact que PSQL le permettra (?). Cela dit, je préférerais arriver à ce genre de syntaxe si possible :

non_null_count(column_1, column_2, column_3) = 1