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