SQL 服务器约束不会保存我定义它的方式
SQL Server constraint won't save the way I define it
我之前注意到 SQL 服务器(或 Management Studio)会在我通过 GUI 创建约束时 "adjust" 检查约束。大多数时候它工作正常且正确。但是这个特定的约束每次都会改变。我什至尝试用脚本来做,但每次都会恢复到不正确的状态。为什么?
这就是我运行:
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
或者,也许您可以建议如何更好地编写此支票?我想确保指定了其中一个键,而不是两个。
事实上,它并没有扼杀逻辑。在 T-SQL 中,precedence 变为 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 服务器将重写约束这一事实,您可以使用不会被重写的形式:
([CarrierKey] IS NULL OR [DriverKey] IS NULL) AND ([DriverKey] IS NOT NULL OR [CarrierKey] IS NOT NULL)
这可以分为两个约束,但由于它们本身没有多大意义,所以我会把它们放在一起。
我之前注意到 SQL 服务器(或 Management Studio)会在我通过 GUI 创建约束时 "adjust" 检查约束。大多数时候它工作正常且正确。但是这个特定的约束每次都会改变。我什至尝试用脚本来做,但每次都会恢复到不正确的状态。为什么?
这就是我运行:
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
或者,也许您可以建议如何更好地编写此支票?我想确保指定了其中一个键,而不是两个。
事实上,它并没有扼杀逻辑。在 T-SQL 中,precedence 变为 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 服务器将重写约束这一事实,您可以使用不会被重写的形式:
([CarrierKey] IS NULL OR [DriverKey] IS NULL) AND ([DriverKey] IS NOT NULL OR [CarrierKey] IS NOT NULL)
这可以分为两个约束,但由于它们本身没有多大意义,所以我会把它们放在一起。