PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Vincolo Postgres che garantisce che sia presente una colonna di tante?

Aggiornamento del 17/09/2021 :Ad oggi, gerardnll fornisce una risposta migliore (il miglior IMO) :

Per aiutare le persone a trovare la soluzione più pulita, ti consiglio di votare risposta di gerardnll .

(Cordiali saluti, sono la stessa persona che ha posto la domanda originale.)

Ecco la mia risposta originale del 2013

Ecco un'elegante soluzione a due colonne secondo il "constraint -- one o l'altra colonna non nulla" bacheca PostgreSQL :

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

(Ma l'approccio di cui sopra non è generalizzabile a tre o più colonne.)

Se hai tre o più colonne, puoi utilizzare l'approccio della tabella di verità illustrato da a_horse_with_no_name . Tuttavia, ritengo che quanto segue sia più facile da mantenere perché non è necessario digitare le combinazioni logiche:

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;

Per compattarlo, sarebbe utile creare una funzione personalizzata in modo che CASE WHEN column_k IS NULL THEN 0 ELSE 1 END boilerplate potrebbe essere rimosso, lasciando qualcosa come:

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

Potrebbe essere compatto quanto lo consentirà PSQL (?). Detto questo, preferirei ottenere questo tipo di sintassi, se possibile:

non_null_count(column_1, column_2, column_3) = 1