编写 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 的一种更好的方法,它检查一个值是不是不为空的主要内容,如果未能解决你的问题,请参考以下文章

无法在 CHECK CONSTRAINT 中引用自定义函数

函数在 sql server 上的 CHECK Constraint 中不起作用

[Oracle]约束(constraint)

提供模板类的一种方法的定义

[ WARN:0@0.010] : can‘t open/read file: check file path/integrity错误的一种解决办法

check约束怎么设置identity11