Sqlalchmey CheckContraint, который проверяет несколько столбцов - PullRequest
1 голос
/ 05 августа 2020

Итак, мы много пытались здесь искать, но, похоже, ни одно из решений не дало ответа на то, что мы ищем. Итак, мы используем sqlalchemy flask, который подключен к базе данных Postgres. У нас есть таблица пользователей, в которой хранятся телефонные номера пользователей и связанные с телефонными номерами пользователей, у нас есть два других столбца, а именно is_primary (это логическое значение, которое определяет, является ли это основным номером телефона пользователя) и текущий (это еще одно логическое значение, определяющее, является ли это текущим номером телефона пользователя).

class Phones(PrimaryCol, DeletedCol, UserTable, IDTable, Base):
    

    __tablename__ = "phones"
    phone = Column(String(50))
    current = Column(Boolean, default=False)
    is_primary = Column(Boolean, default=False)
    CheckConstraint(
            "(NOT is_primary OR current OR (is_primary = true AND current = true))",
            name="my_contraint",
        )

Теперь проблема заключается в проверочном ограничении. Позвольте мне сказать вам, чего мы пытаемся этим достичь. Итак, мы хотим добавить проверку по нескольким столбцам: если is_primary истинно, то current должно быть истинным по умолчанию и не может быть ложным, а если is_primary - false, тогда current может иметь значение true или false. Итак, увидев шаблон, используемый для UniqueContraint ( Как определяется уникальное ограничение для трех столбцов? ), мы пытались эмулировать это в CheckContraint, но не работает, имея в виду, что он позволяет current быть T / f, если is_primary правда. (чего мы не хотим и хотим, чтобы база данных выдавала ошибку). Может ли кто-нибудь помочь нам с тем, как мы можем добавить CheckContraint, который выполняет проверку значений нескольких столбцов.

1 Ответ

2 голосов
/ 05 августа 2020

Составьте таблицу истинности для облегчения понимания:

p | c | result
--------------
T | T | valid
T | F | invalid
F | T | valid
F | F | valid

Единственное условие, которое вы хотите избежать, - это (is_primary and not current), поэтому сделайте ваше ограничение not (is_primary and not current), которое можно уменьшить до (not is_primary or current).

p | c | not is_primary or current
------------------------------------
T | T | T
T | F | F
F | T | T
F | F | T

(преобразование запомнилось из класса Digital Computer Logi c, потому что вентили NAND были дешевыми).

...