NOT NULL ограничение по набору столбцов

У меня есть таблица в Postgres, которая в настоящее время имеет ограничение NOT NULL на столбце email. В этой таблице также есть столбец phone, который является необязательным. Я хотел бы, чтобы система принимала некоторые записи без email, но только если они имеют phone как NOT NULL. Другими словами, мне нужно ограничение базы данных NOT NULL, чтобы запросы CREATE или UPDATE выполнялись без каких-либо ошибок, если присутствует один или оба поля email или phone.

Расширение вышеизложенного, возможно ли в Postgres указать набор имен столбцов, один или несколько из которых должны быть NOT NULL, чтобы запись была успешно обновлена ​​или создана?

Ответ 1

@Igor совершенно прав, и несколько выражений OR 'ed бывают быстрыми и простыми.

Для длинного списка столбцов (a, b, c, d, e, f, g в этом примере) это короче и так же быстро:

CHECK (NOT (a,b,c,d,e,f,g) IS NULL)

Скрипт SQL Fiddle.

Как это работает?

Более сложной формой выше было бы:

CHECK (NOT ROW(a,b,c,d,e,f,g) IS NULL)

ROW здесь избыточный синтаксис.

Тестирование выражения ROW с IS NULL сообщает только TRUE, если каждый столбец равен NULL - это именно то, что мы исключаем.

Невозможно просто отменить это выражение с помощью (a,b,c,d,e,f,g) IS NOT NULL, потому что это проверит, что каждый столбец IS NOT NULL. Вместо этого отрицайте все выражение с помощью NOT. Вуаля.

Подробнее в руководстве здесь и здесь.

Выражение вида:

CHECK (COALESCE(a,b,c,d,e,f,g) IS NOT NULL)

достигнет того же, менее изящно и с большим ограничением: работает только для столбцов совпадающего типа данных, а проверка выражения ROW работает с любыми столбцами.

Ответ 2

Для этого можно использовать ограничение CHECK. Что-то вроде:

CHECK (email is not null OR phone is not null)

Подробности о ограничениях можно найти here