Есть ли способ заставить обнуляемость столбца зависеть от обнуляемости другого столбца? - PullRequest
11 голосов
/ 04 ноября 2011

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

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

Ответы [ 5 ]

13 голосов
/ 04 ноября 2011

Если вы используете 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 ...
);

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

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

Этого можно добиться, разделив эти два столбца в отдельную таблицу «даты выхода» и сделав их необнуляемыми, но было бы неплохо, если бы мне это не понадобилось.

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

1 голос
/ 03 апреля 2012

Можно использовать проверки с 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

1 голос
/ 03 апреля 2012

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)
0 голосов
/ 04 ноября 2011

Вы можете применить это с помощью триггера: если вы устанавливаете ExitDate для чего-то отличного от NULL, а ExitReason остается нулевым или имеет значение NULL, вы выдаете ошибку.

...