编写 CHECK CONSTRAINT 的一种更好的方法,它检查一个值是不是不为空
Posted
技术标签:
【中文标题】编写 CHECK CONSTRAINT 的一种更好的方法,它检查一个值是不是不为空【英文标题】:A nicer way to write a CHECK CONSTRAINT that checks that exactly one value is not null编写 CHECK CONSTRAINT 的一种更好的方法,它检查一个值是否不为空 【发布时间】:2011-08-24 10:45:35 【问题描述】:假设我有一个包含整数列 Col1、Col2、Col3、Col4 的表。每列都可以为空,并且有效行必须包含恰好 1 列中的值(即所有空值都无效,多于 1 列也无效)。
目前我有这样的检查约束
ALTER TABLE [dbo].[MyTable] WITH CHECK
ADD CONSTRAINT [CK_ReportTemplateAttributes] CHECK
((
[Col1] IS NOT NULL AND [Col2] IS NULL AND [Col3] IS NULL AND [Col4] IS NULL
OR
[Col1] IS NULL AND [Col2] IS NOT NULL AND [Col3] IS NULL AND [Col4] IS NULL
OR
[Col1] IS NULL AND [Col2] IS NULL AND [Col3] IS NOT NULL AND [Col4] IS NULL
OR
[Col1] IS NULL AND [Col2] IS NULL AND [Col3] IS NULL AND [Col4] IS NOT NULL
));
GO;
它有效,但令我震惊的是,可能有一种更优雅的方式来实现相同的结果(例如,this questioner 想要检查至少 1 个字段不为空,而 COALESCE
关键字在这种情况下效果很好)。
【问题讨论】:
对我来说,你的约束比接受的答案更清楚。无论哪种方式,我都觉得有一点设计问题的味道:也许是表格没有完全标准化?也许真实的列名会提供更多线索(希望那些不是真实的名字!) 【参考方案1】:在这里重复另一个答案,我认为这是更多的自我记录:
ALTER TABLE [dbo].[MyTable] WITH CHECK
ADD CONSTRAINT [CK_ReportTemplateAttributes] CHECK
(1 = CASE when [Col1] IS NULL THEN 0 ELSE 1 END +
CASE when [Col2] IS NULL THEN 0 ELSE 1 END +
CASE when [Col3] IS NULL THEN 0 ELSE 1 END +
CASE when [Col4] IS NULL THEN 0 ELSE 1 END ) ;
它还有一个好处是避免了您更改约束以考虑另一列但忘记将“3”更新为“[约束中的列数] - 1”的错误。
【讨论】:
我也喜欢你的方式 Ben(虽然你需要将“IS NULL”更改为“IS NOT NULL”)。我个人更喜欢 Martin 的回答,但我团队的其他成员不同意。 如果他们不同意,请他们对 10 列进行案例分析,其中 2 列可以是非空的。这种方法在开发工作中可以很好地扩展。另一个没有。此外,我的答案已根据要求进行了编辑。【参考方案2】:目前我能想到的最简洁的方式是。
ALTER TABLE [dbo].[MyTable] WITH CHECK
ADD CONSTRAINT [CK_ReportTemplateAttributes] CHECK
(3 = ISNULL([Col1] - [Col1],1) +
ISNULL([Col2] - [Col2],1) +
ISNULL([Col3] - [Col3],1) +
ISNULL([Col4] - [Col4],1)) ;
【讨论】:
就我个人而言,我更喜欢这个检查约束,而不是我发布的(详细)检查,但刚刚对我组中的其他开发人员进行了一次民意调查,响亮的答案是没有人确定什么行为ISNULL 方法会 - 这让我很惊讶。以上是关于编写 CHECK CONSTRAINT 的一种更好的方法,它检查一个值是不是不为空的主要内容,如果未能解决你的问题,请参考以下文章
函数在 sql server 上的 CHECK Constraint 中不起作用
[ WARN:0@0.010] : can‘t open/read file: check file path/integrity错误的一种解决办法