Проверить ограничение для взаимоисключающих столбцов в SQLAlchemy

Если у меня есть декларативная модель SQLAlchemy, как показано ниже:

class Test(Model): __tablename__ = 'tests' id = Column(Integer, Sequence('test_id_seq'), primary_key=True) ... Atest_id = Column(Integer, ForeignKey('Atests.id'), nullable=True) Btest_id = Column(Integer, ForeignKey('Btests.id'), nullable=True) Ctest_id = Column(Integer, ForeignKey('Ctests.id'), nullable=True) Dtest_id = Column(Integer, ForeignKey('Dtests.id'), nullable=True) Etest_id = Column(Integer, ForeignKey('Etests.id'), nullable=True) ... date = Column(DateTime) status = Column(String(20)) # pass, fail, needs_review 

И я хотел бы убедиться, что в заданной строке присутствует только один из *test_id внешних ключей *test_id , как я могу это сделать в SQLAlchemy ?

Я вижу, что есть объект SQLAlchemy CheckConstraint (см. CheckConstraint ) , но MySQL не поддерживает проверки ограничений.

Модель данных имеет взаимодействие вне SQLAlchemy , поэтому желательно, чтобы это была проверка уровня базы данных ( MySQL )

One Solution collect form web for “Проверить ограничение для взаимоисключающих столбцов в SQLAlchemy”

Ну, учитывая ваши реквизиты «Модель данных имеет взаимодействие вне SQLAlchemy, поэтому желательно, чтобы это была проверка уровня базы данных (MySQL)» и «убедитесь, что только один [..] не является нулевым» . Я думаю, что лучший подход – написать триггер следующим образом:

 DELIMITER $$ CREATE TRIGGER check_null_insert BEFORE INSERT ON my_table FOR EACH ROW BEGIN IF CHAR_LENGTH(CONCAT_WS('', NEW.a-NEW.a, NEW.b-NEW.b, NEW.c-NEW.c)) = 1 THEN UPDATE `Error: Only one value of *test_id must be not null` SET z=0; END IF; END$$ DELIMITER ; 

Некоторые трюки и соображения:

  1. ЕСЛИ ЗАЯВЛЕНИЕ : во избежание утомительной записи проверки каждый столбец не является нулевым, а другие равны нулю, я сделал этот трюк: уменьшите каждый столбец до одного символа и проверьте, сколько символов существует. Обратите внимание, что NEW.a-NEW.a всегда возвращает 1 символ, если NEW.a является Integer , NULL возвращает 0 символов, а операция NULL-NULL возвращает NULL в MySQL.

  2. ERROR TRIGGERING : Я предполагаю, что вы хотите поднять ошибку, и как это сделать в MySQL? Вы не упомянули версию MySQL. Только для MySQL 5.5 вы можете использовать синтаксис SIGNAL для генерирования исключения . Таким образом, более переносимый способ выдает недопустимый оператор: UPDATE xx SET z=0 . Если вы используете MySQL 5.5, вы можете использовать: signal sqlstate '45000' set message_text = 'Error: Only one value of *test_id must be not null'; вместо UPDATE `Error: Only one value of *test_id must be not null` SET z=0;

Кроме того, я думаю, вы тоже хотите проверить это на обновлениях, поэтому используйте:

 DELIMITER $$ CREATE TRIGGER check_null_update BEFORE UPDATE ON my_table FOR EACH ROW BEGIN IF CHAR_LENGTH(CONCAT_WS('', NEW.a-NEW.a, NEW.b-NEW.b, NEW.c-NEW.c)) = 1 THEN UPDATE `Error: Only one value of *test_id must be not null` SET z=0; END IF; END$$ DELIMITER ; 

Или создайте хранимую процедуру и вызовите ее.

Обновить

Для баз данных, которые поддерживают контрольные ограничения , код более прост, см. Этот пример для SQL Server :

 CREATE TABLE MyTable (col1 INT NULL, col2 INT NULL, col3 INT NULL); GO ALTER TABLE MyTable ADD CONSTRAINT CheckOnlyOneColumnIsNull CHECK ( LEN(CONCAT(col1-col1, col2-col2, col3-col3)) = 1 ) GO 
  • Оптимизация SqlAlchemy для объектных моделей только для чтения
  • Переименование столбцов при запросе SQLAlchemy в Pandas DataFrame
  • SQLAlchemy - использование 'aliased' в запросе с пользовательским отношением primaryjoin
  • Создайте динамическую форму, используя флягу-wtf и sqlalchemy
  • Sqlalchemy json column - как выполнить предварительный запрос a содержит запрос
  • Многопоточное использование SQLAlchemy
  • Управление значением, возвращаемым порожденным процессом
  • Flask унаследовал классы таблиц в нескольких идентичных базах данных, используя __bind_key__
  •  
    Interesting Posts for Van-Lav

    Размер BoundingBox / ROI для отслеживания объекта продолжает расти, несмотря на фиксированный начальный размер

    Есть ли масштабированная дополнительная функция ошибки в python?

    Как выглядит «файл версии»?

    Python: определение префикса из набора (похожих) строк

    Как использовать IE webdriver из selenium для python (Не удалось найти ошибку)?

    Заменить строку в определенной строке с помощью python

    Получить или создать соответствующий ключ и пользователь (Python – движок приложения)

    scrap scrap на всех страницах, у которых есть этот синтаксис

    paramiko SSH exec_command (сценарий оболочки) возвращается до завершения

    Не удается разрешить «django.utils.log.NullHandler» в Django 1.9+

    подпиксельный модуль python

    Создание матрицы индикаторов из двух массивов в Python Numpy

    Неожиданный вывод метода Ньютона

    Является ли какой-либо магический метод вызовом объекта в списке во время join ()?

    Как перебирать все узлы дерева?

    Python - лучший язык программирования в мире.