Есть ли способ, чтобы нулевое значение столбца зависело от другой ошибки?

У меня есть два столбца (среди прочих) в таблице базы данных: ExitDate и ExitReason. Наша бизнес-логика требует указания ExitReason, если указан ExitDate. Столбец ExitDate должен допускать нулевые значения, поскольку значение не всегда известно во время ввода. Есть ли способ заставить столбец ExitReason разрешать null, только если значение ExitDate равно null? Я мог бы добиться эффекта, разделив эти два столбца на отдельную таблицу "даты выхода" и сделав их непустыми, но было бы неплохо, если бы мне не пришлось.

Идеи? Спасибо!

Ответ 1

Предполагая, что вы находитесь на SQL Server или что-то подобное, вы можете сделать это с помощью CHECK constraint в своей таблице. (К сожалению, 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 ...
);

Использование контрольного ограничения предпочтительнее использования триггера, потому что:

  • контрольные ограничения более заметны, чем триггеры
  • ограничение является частью определения таблицы, в отличие от кода, который запускается отдельно, поэтому он логически более чистый
  • Я готов поспорить, что это быстрее, чем триггер.

Ответ 2

Я мог бы выполнить эффект, разделив эти два столбца на отдельную таблицу "даты выхода" и сделав их непустыми, но было бы неплохо, если бы мне не пришлось.

Это похоже на очень хорошее решение. И если вы используете MySQL, то это, вероятно, лучшее решение, поскольку ограничения CHECK не поддерживаются.

Ответ 3

MS Access предлагает другой метод для достижения вашей цели. С помощью таблицы в Design View откройте лист свойств. В отличие от правила проверки для поля правило таблицы может ссылаться на другие поля в таблице.

Добавьте это как одну строку для свойства правила проверки таблицы.

([ExitDate] IS NULL AND [ExitReason] IS NULL) 
OR ([ExitDate] IS NOT NULL AND [ExitReason] IS NOT NULL)

Он похож на поставляемый CHECK CONSTRAINT @NickChammas. Я помещаю квадратные скобки вокруг ExitDate и ExitReason, потому что без скобок Access стремится интерпретировать их как значения текстового литерала, поэтому добавляет такие кавычки... что не будет работать:

("ExitDate" IS NULL AND "ExitReason" IS NULL) 
OR ("ExitDate" IS NOT NULL AND "ExitReason" IS NOT NULL)

Вы можете найти этот метод более удобным, если вы хотите включить удобное для пользователя сообщение в качестве свойства таблицы Validation Text для отображения при нарушении правила проверки:

"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 " _
& "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 на что-то отличное от нуля, а ExitReason остается нулевым или имеет значение null, то вы вызываете ошибку.