Aktualizacja 2021-09-17 :Na dzień dzisiejszy gerardnll zapewnia lepszą odpowiedź (najlepsza IMO) :
Aby pomóc ludziom znaleźć najczystsze rozwiązanie, polecam zagłosować za odpowiedzią gerardnll .
(FYI, jestem tą samą osobą, która zadała pierwotne pytanie).
Oto moja oryginalna odpowiedź z 2013 roku
Oto eleganckie rozwiązanie dwukolumnowe zgodnie z "ograniczenie -- jeden lub inna kolumna nie jest pusta" Tablica wiadomości PostgreSQL :
ALTER TABLE my_table ADD CONSTRAINT my_constraint CHECK (
(column_1 IS NULL) != (column_2 IS NULL));
(Ale powyższego podejścia nie można uogólnić na trzy lub więcej kolumn).
Jeśli masz co najmniej trzy kolumny, możesz użyć metody tabeli prawdy przedstawionej przez a_horse_with_no_name . Uważam jednak, że poniższe są łatwiejsze w utrzymaniu, ponieważ nie trzeba wpisywać logicznych kombinacji:
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;
Aby to skondensować, warto utworzyć funkcję niestandardową, tak aby CASE WHEN column_k IS NULL THEN 0 ELSE 1 END
boilerplate mógł zostać usunięty, pozostawiając coś takiego:
(non_null_count(column_1) +
non_null_count(column_2) +
non_null_count(column_3)) = 1
To może być tak zwarte, jak pozwoli na to PSQL (?). To powiedziawszy, w miarę możliwości wolę przejść do tego rodzaju składni:
non_null_count(column_1, column_2, column_3) = 1