跨两列创建独占OR约束

Evi*_*lDr 2 t-sql sql-server sql-server-2012

我有一个有两列的表(其中包括):

NotApplicable  bit
TargetLevel    numeric(5,2)
Run Code Online (Sandbox Code Playgroud)

我需要创建一个约束,以下规则适用:

  1. NotApplicable和TargetLevel不能都是NULL
  2. NotApplicable和TargetLevel都不能都有值
  3. NotApplicable或TargetLevel必须具有值

我想这是一个独家OR场景?我有一段时间回来了,但我现在意识到这不能解释上面的最后一个场景:

ALTER TABLE [dbo].[my_Table] ADD CONSTRAINT [DF_tbl_my_Table_notApplicable] DEFAULT ((0)) FOR [notApplicable]
GO
ALTER TABLE [dbo].[my_Table] WITH CHECK ADD CONSTRAINT [CK_tbl_my_Table] CHECK  ((COALESCE([targetLevel],[notapplicable]) IS NOT NULL))
GO
ALTER TABLE [dbo].[my_Table] CHECK CONSTRAINT [CK_tbl_my_Table]
GO
Run Code Online (Sandbox Code Playgroud)

任何帮助完善这一点将不胜感激.另外,上面的例子中实际需要的最后一个ALTER语句是吗?

Dam*_*ver 7

它有点冗长,但我这样做的标准方法就是:

ALTER TABLE T ADD CONSTRAINT CK_One_Or_Tother CHECK (
    (NotApplicable IS NULL and TargetLevel IS NOT NULL) OR
    (NotApplicable IS NOT NULL and TargetLevel IS NULL)
)
Run Code Online (Sandbox Code Playgroud)

另外,上面的例子中实际需要的最后一个ALTER语句是吗?

ALTER TABLE [dbo].[my_Table] CHECK CONSTRAINT [CK_tbl_my_Table]
Run Code Online (Sandbox Code Playgroud)

只有在您创建或更改约束并指定约束NOCHECK或以其他方式禁用先前的约束并现在启用约束时,才需要执行此操作.创建约束的默认设置是启用它们.


对于大量的列,必须填写一个列,我倾向于切换到另一种结构:

ALTER TABLE T ADD CONSTRAINT CK_One_Or_Tother CHECK (
    1 = (
        CASE WHEN ColumnA IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN ColumnB IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN ColumnC IS NOT NULL THEN 1 ELSE 0 END +
        CASE WHEN ColumnD IS NOT NULL THEN 1 ELSE 0 END
    )
)
Run Code Online (Sandbox Code Playgroud)

它的优点是只能命名每列一次,但看起来有点难看.