CHECK 约束可以像 if else 那样起作用吗?
Posted
技术标签:
【中文标题】CHECK 约束可以像 if else 那样起作用吗?【英文标题】:Can CHECK constraints act like if else? 【发布时间】:2013-08-09 12:11:53 【问题描述】:我有一个有 4 列的表格:
(ID (PK, int, NOT NULL), col1 (NULL), col2 (NULL), col3 (NULL))
我想添加一个CHECK
约束(我认为是表级的?)这样:
if col1 OR col2 are NOT NULL then col3 must be NULL
和
if col3 is NOT NULL then col1 AND col2 must be NULL
即如果col1
和col2
不为空,则col3
应为null
,反之亦然
虽然我对 SQL 和 SQL Server 很陌生,但不确定如何实际实现它,或者即使它可以/应该实现?
我想也许:
CHECK ( (col1 NOT NULL OR col2 NOT NULL AND col3 NULL) OR
(col3 NOT NULL AND col1 NULL AND col2 NULL) )
但我不确定括号是否可以用来对这样的逻辑进行分组?如果没有,如何最好地实施?
【问题讨论】:
不,我的表在一个实时服务器上,还有很多其他的东西可以使用,所以我不想搞砸了:O 你没有同等的开发环境吗? 不,也没有办法在这里设置,否则我将如何开始(也正如我提到的我在 SQL 方面非常新,不知道从哪里开始设置 SQL 服务器或数据库从头开始) 是的,你可以做到,但有一件事情会引起人们的注意——如果你创建它,然后从对象生成一个脚本,你的包围和布局可能看起来不同。我不确定它们是如何存储的,但它不是作为字符串,因此当重新生成字符串时,只会添加严格必要的括号。 SQL Server Developer Edition 如果您直接从 MS 购买,则需要 60 美元(您可以在其他地方找到更便宜的 - 在 Newegg 上 50 美元,在亚马逊上更便宜),您可以将它安装在您的工作站上。您需要一个非生产环境来学习和测试事物。 【参考方案1】:当然,你可以做到这一点。看到这个sqlfiddle。
但是,您需要确保正确地将逻辑括起来。您应该切勿在同一括号范围内混用 AND 和 OR。所以:
(col1 NOT NULL OR col2 NOT NULL AND col3 NULL)
需要成为:
((col1 NOT NULL OR col2 NOT NULL) AND col3 NULL)
或者:
(col1 NOT NULL OR (col2 NOT NULL AND col3 NULL))
取决于你的意图。
【讨论】:
谢谢 - 也谢谢你展示 sqfiddle,不知道存在,会很方便:) 但它会检查这两种情况是否也意味着反之亦然?? @Dhaval:您可能的意思是指出逻辑应该只是( (col1 NOT NULL AND col2 NOT NULL AND col3 NULL) OR (col3 NOT NULL AND col1 NULL AND col2 NULL) )
。这样做的问题是它将始终强制 col1
和 col2
具有相同的状态。我认为 OP 故意没有这样做,因为如果 col1
或 col2
中的 一个 不为空,col3
应该为空。
@PinnyM 正确,如果 col1 或 col2 的 either 不为 null,则 Col3 需要为 null。但是 col1 和 col2 应该 both 为 null 或不为 null together - 但我可以强制执行此应用程序端,否则我认为关于 this 和 col3 的约束变得有点复杂【参考方案2】:
注意不要用括号弄错。
CREATE TABLE Test1 (col1 INT, col2 INT, col3 INT);
ALTER TABLE Test1
ADD CONSTRAINT CHK1
CHECK (((col1 IS NOT NULL OR col2 IS NOT NULL) AND col3 IS NULL) OR
((col1 IS NULL AND col2 IS NULL) AND col3 IS NOT NULL))
INSERT INTO Test1 VALUES (1,1,1); --fail
INSERT INTO Test1 VALUES (1,1,NULL); --good
INSERT INTO Test1 VALUES (1,NULL,NULL); --good
INSERT INTO Test1 VALUES (1,NULL,1); --fail
INSERT INTO Test1 VALUES (NULL,NULL,1); --good
【讨论】:
【参考方案3】:我会说创建一个像下面这样的 UDF
create FUNCTION dbo.fn_check_val
(@col1 int , @col2 int , @col3 int)
RETURNS bit
AS
BEGIN
declare @toRet bit
IF(@col1 is Not null OR @col2 is NOT NULL)
Begin
if(@col3 is null)
Begin
Set @toRet = 1
End
Else
Begin
Set @toRet = 0
End
End
Else
if(@col3 is not null)
Begin
Set @toRet = 1
End
Else
Begin
Set @toRet = 0
End
return @toRet
END
然后在您的表格中添加以下检查语句
([dbo].[fn_check_val]([col1],[col2],[col3])=(1))
【讨论】:
哇,这太让我头疼了!你能解释一下为什么这样做会比简单的 AND/OR 约束更好吗? @Toby ..你是对的...我刚刚试图解释这可以做到以上是关于CHECK 约束可以像 if else 那样起作用吗?的主要内容,如果未能解决你的问题,请参考以下文章