我之前注意到SQL Server(或Management Studio)会调整"通过GUI创建时检查约束。大多数时候它工作正常。但是这种特殊的约束每次都会改变。我甚至尝试在脚本中执行此操作但每次都会恢复为不正确的。为什么呢?
这就是我的目的:
ALTER TABLE [dbo].[DSPTripAssignment] WITH CHECK
ADD CONSTRAINT [CK_DSPTripAssignment_CarrierKey_DriverKey]
CHECK (([CarrierKey] IS NULL AND NOT [DriverKey] IS NULL)
OR ([DriverKey] IS NULL AND NOT [CarrierKey] IS NULL))
GO
这是它恢复的原因(见OR周围缺少大括号 - 杀死逻辑)
ALTER TABLE [dbo].[DSPTripAssignment] WITH CHECK
ADD CONSTRAINT [CK_DSPTripAssignment_CarrierKey_DriverKey]
CHECK (([CarrierKey] IS NULL AND NOT [DriverKey] IS NULL
OR [DriverKey] IS NULL AND NOT [CarrierKey] IS NULL))
GO
或者,也许您可以建议如何更好地编写此检查?我想确保指定其中一个键,但不是两个。
答案 0 :(得分:2)
NOT
> AND
> OR
,所以
A AND NOT B OR C AND NOT D
与
相同(A AND (NOT B)) OR (C AND (NOT D))
遗漏了多余的括号。检查定义会被重写为可能不太可读的规范形式,但这不会导致错误检查。
您的实际支票定义很好 - 虽然您可以使用ISNULL
/ COALESCE
/ CASE
进行重写,但这可能会降低检查效率。但是,您可以将NOT X IS NULL
重写为X IS NOT NULL
,我认为这更具可读性:
([CarrierKey] IS NULL AND [DriverKey] IS NOT NULL) OR ([DriverKey] IS NULL AND [CarrierKey] IS NOT NULL)
如果您不喜欢SQL Server将重写约束的事实,您可以使用不会被重写的表单:
([CarrierKey] IS NULL OR [DriverKey] IS NULL) AND ([DriverKey] IS NOT NULL OR [CarrierKey] IS NOT NULL)
这可以分为两个约束,但由于这些约束本身没有多大意义,我会将它们保持在一起。