我有一个包含两列的表格(其中包括):
NotApplicable bit
TargetLevel numeric(5,2)
我需要创建一个约束,以下规则适用:
我猜这是一个独家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
任何帮助完善这一点将不胜感激。另外,上面例子中实际需要的最后一个ALTER语句是吗?
答案 0 :(得分: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)
)
另外,上面的例子中实际需要的最后一个ALTER语句是吗?
ALTER TABLE [dbo].[my_Table] CHECK CONSTRAINT [CK_tbl_my_Table]
只有在您创建或更改约束并指定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
)
)
这样做的好处是只能为每一列命名一次,但看起来有点难看。
答案 1 :(得分:0)
两列方案的替代语法是:
ALTER TABLE T ADD CONSTRAINT CK_One_Or_Tother CHECK (
(NotApplicable IS NULL OR TargetLevel IS NULL)
AND (NotApplicable IS NOT NULL OR TargetLevel IS NOT NULL)
)