Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 检查约束的行为是否与if-else类似?_Sql_Sql Server_Check Constraints - Fatal编程技术网

Sql 检查约束的行为是否与if-else类似?

Sql 检查约束的行为是否与if-else类似?,sql,sql-server,check-constraints,Sql,Sql Server,Check Constraints,我有一个包含4列的表: (ID (PK, int, NOT NULL), col1 (NULL), col2 (NULL), col3 (NULL)) 我想添加一个检查约束(我想是表级的吧?),以便: 及 i、 e.col3如果col1和col2不为空,则应为null 不过,我对SQL和SQL server非常陌生,不知道如何实际实现它,甚至不知道它是否可以/应该实现 我想也许: CHECK ( (col1 NOT NULL OR col2 NOT NULL AND col3 NULL) OR

我有一个包含4列的表:

(ID (PK, int, NOT NULL), col1 (NULL), col2 (NULL), col3 (NULL))
我想添加一个
检查
约束(我想是表级的吧?),以便:

i、 e.
col3
如果
col1
col2
不为空,则应为
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) )

但我不确定是否可以用括号来分组这样的逻辑?如果没有,如何才能最好地实现这一点?

当然,您可以这样做。看这个

然而,你需要确保你的逻辑正确。您不应在同一括号内混合and和OR。因此:

(col1 NOT NULL OR col2 NOT NULL AND col3 NULL)
需要成为:

((col1 NOT NULL OR col2 NOT NULL) AND col3 NULL)
或:


取决于您的意图。

注意不要在括号中出错

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

我会说创建一个如下所示的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
然后在表中添加以下check语句

([dbo].[fn_check_val]([col1],[col2],[col3])=(1))

不,我的表在一个实时服务器上,有很多其他工作需要的东西,所以我不想把事情搞砸:难道你没有一个同等的开发环境吗?不,也没有办法在这里设置一个,否则我就这样开始了(正如我提到的,我对SQL非常陌生,不知道从哪里开始从头开始设置SQL server或DB)是的,你可以这样做,但有一件事让人们很感兴趣——如果你创建了它,然后从对象生成了一个脚本,你的括号和布局可能会有所不同。我不确定它们是如何存储的,但它不是一个字符串,所以当重新生成字符串时,只有严格必要的括号才会添加到.SQL Server Deve中如果您直接从MS购买,loper Edition的价格为60美元(您可以在其他地方找到更便宜的版本,在Newegg上为50美元,在Amazon上甚至更低),并且您可以将其安装在您的工作站上。您需要一个非生产环境来学习和测试内容。谢谢-还感谢您展示sqfiddle,我不知道它的存在,这将非常方便:)但是它会同时检查这两个条件吗?也意味着viceversa???@Dhaval:您可能想指出逻辑应该是
((col1不为NULL,col2不为NULL,col3为NULL)或(col3不为NULL,col1为NULL,col2为NULL))
。这样做的问题是,它总是强制执行
col1
col2
具有相同的状态。我认为OP故意没有这样做,因为如果
col1
col2
中的一个不为空,则
col3
应该为空。@PinnyM正确,如果col1或col2中的任何一个不为空,则col3需要为空。但是col1和col2应该同时为null或者不为null——但是我可以强制这个应用程序端,否则我认为关于这个和col3的约束会变得更复杂一点哇,这已经超出我的理解了!你能解释一下为什么这样做比简单的和/或约束更好吗?@Toby。。你是对的。。。我刚才试图解释这是可以做到的
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
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))