#sql #ms-access #nullable
#sql #ms-access #обнуляемый
Вопрос:
У меня есть два столбца (среди прочих) в таблице базы данных: ExitDate и ExitReason. Наша бизнес-логика требует, чтобы ExitReason был указан, если указан ExitDate. Столбец ExitDate должен разрешать значения null, поскольку значение не всегда известно во время вставки. Есть ли способ заставить столбец ExitReason разрешать значения null, только если значение ExitDate равно null? Я мог бы добиться эффекта, разделив эти два столбца на отдельную таблицу «даты выхода» и сделав их оба ненулевыми, но было бы неплохо, если бы мне не пришлось этого делать.
Идеи? Спасибо!
Комментарии:
1. Вы пытались написать триггер?
Ответ №1:
Предполагая, что вы используете SQL Server или что-то подобное, вы можете сделать это с CHECK
ограничением для вашей таблицы. (К сожалению, MySQL анализирует, но игнорирует CHECK
ограничения, поэтому вам придется использовать триггер для этой платформы.)
Если таблица уже существует:
ALTER TABLE ADD CONSTRAINT CK_ExitDateReason
CHECK (
(ExitDate IS NULL AND ExitReason IS NULL)
OR (ExitDate IS NOT NULL AND ExitReason IS NOT NULL)
);
Если вы создаете таблицу самостоятельно:
CREATE TABLE dbo.Exit (
...
, CONSTRAINT CK_ExitDateReason CHECK ...
);
Использование ограничения проверки предпочтительнее использования триггера, потому что:
- ограничения проверки более заметны, чем триггеры
- ограничение является частью определения таблицы, в отличие от кода, который выполняется отдельно, поэтому он логически более чистый
- Я готов поспорить, что это быстрее, чем триггер
Комментарии:
1. 1 Такой хороший ответ для «кого-то настолько молодого» (в любом случае, с точки зрения репутации). Продолжайте в том же духе 🙂
2. @Bohemian — Спасибо! У меня есть небольшой опыт работы с этими стеками . 🙂
3. И если используемая платформа позволяет сравнивать результаты логических выражений, то выражение проверки может быть таким простым, как
(ExitDate IS NULL) = (ExitReason IS NULL)
.4. @AndriyM — Хорошее предложение. К сожалению, это невозможно в SQL Server.
5. К вашему сведению, ограничения ПРОВЕРКИ поддерживаются Mysql начиная с версии 8.0.16. Дополнительная информация: dev.mysql.com/doc/refman/8.0/en /…
Ответ №2:
Я мог бы добиться эффекта, разделив эти два столбца на отдельную таблицу «даты выхода» и сделав их оба ненулевыми, но было бы неплохо, если бы мне не пришлось этого делать.
Это звучит как очень хорошее решение. И если вы используете MySQL, то это, вероятно, лучшее решение, поскольку ограничения ПРОВЕРКИ не поддерживаются.
Ответ №3:
MS Access предлагает другой метод для достижения вашей цели. С таблицей в режиме конструктора откройте таблицу свойств. В отличие от правила проверки для поля, правило таблицы может ссылаться на другие поля в таблице.
Добавьте это в виде одной строки для свойства правила проверки таблицы.
([ExitDate] IS NULL AND [ExitReason] IS NULL)
OR ([ExitDate] IS NOT NULL AND [ExitReason] IS NOT NULL)
Это похоже на ОГРАНИЧЕНИЕ ПРОВЕРКИ, предоставленное @NickChammas. Я заключил в квадратные скобки ExitDate и ExitReason, потому что без скобок Access обычно интерпретирует их как текстовые литеральные значения, поэтому добавляет кавычки, подобные этому … что не сработает:
("ExitDate" IS NULL AND "ExitReason" IS NULL)
OR ("ExitDate" IS NOT NULL AND "ExitReason" IS NOT NULL)
Возможно, этот метод покажется вам более удобным, если вы хотите включить удобное для пользователя сообщение в качестве свойства текста проверки таблицы для отображения при нарушении правила проверки:
"Provide values for both ExitDate and ExitReason, or leave both blank."
Редактировать: Предложение @AndriyM работает как правило проверки таблицы MS Access:
([ExitDate] Is Null) = ([ExitReason] Is Null)
Ответ №4:
Можно использовать проверки с MS Access, но только через ADO.
sSQL = "ALTER TABLE customer ADD CONSTRAINT CK_ExitDateReason " _
amp; "CHECK ((ExitDate IS NULL) = (ExitReason IS NULL))"
CurrentProject.Connection.Execute sSQL
Ограничение может быть удалено только с помощью ADO. Тем не менее, вы можете добавлять и удалять столбцы (поля), не влияя на проверку.
Также можно добавить проверку, которая ссылается на другую таблицу.
Если вы используете таблицу с формой, возвращаемая ошибка будет 3317. Вы можете либо принять сообщение по умолчанию, либо предоставить свое собственное, например:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
If DataErr = 3317 And IsNull(Me.ExitReason) Then
MsgBox "Please fill in a reason"
Response = acDataErrContinue
End If
End Sub
Дополнительная информация: Промежуточный Microsoft Jet SQL для Access 2000
Ответ №5:
Вы могли бы применить это с помощью триггера: если вы устанавливаете ExitDate на что-то другое, кроме null, и ExitReason остается нулевым или устанавливается равным null, тогда вы выдаете ошибку.