检查约束不会在SQL Server 2016

问题描述:

工作,我有以下检查约束不会在SQL Server 2016

begin tran 

CREATE TABLE [dbo].[Filters] 
(
    [Id]     INT NOT NULL IDENTITY, 
    [FCode]     varchar(30) null, 
    [FVersion]    varbinary(892) null, 

    CONSTRAINT [PK_Filter] PRIMARY KEY CLUSTERED ([Id]), 

    CONSTRAINT [CK_Filters_FCode_FVersion] 
     CHECK (([FCode] IS NULL AND [FVersion] IS NULL) 
       OR (LEN([FCode]) > 0 AND DATALENGTH([FVersion]) > 0)), 
) 

INSERT INTO [dbo].[Filters] (FCode, FVersion) 
VALUES (NULL, NULL), 
     (NULL, 0x6BE348), 
     ('ASD', NULL), 
     ('ASD', 0x6BE348) 

SELECT 
    IIF(([FCode] IS NULL AND [FVersion] IS NULL) 
     OR (LEN([FCode]) > 0 AND DATALENGTH([FVersion]) > 0) , 1, 0) AS [check], * 
FROM 
    [dbo].[filters] 

rollback 

我想到的是,第二和第三插入语句会导致违反约束一个简单的例子。但是服务器允许它们。

使用select语句查看第2行和第3行违反约束检查的值。查看结果

check Id FCode FVersion 
------------------------------ 
1  1 NULL NULL 
0  2 NULL 0x6BE348 
0  3 ASD  NULL 
1  4 ASD  0x6BE348 

任何想法?

检查约束条件只有当值为最终值时才会失败false

您希望违反约束条件的表达式评估为UNKNOWN

您可以

​​

它返回

+---------+----------+--------------------+----+-------+----------+ 
| check | LenFCode | DataLengthFVersion | Id | FCode | FVersion | 
+---------+----------+--------------------+----+-------+----------+ 
| True | NULL  | NULL    | 1 | NULL | NULL  | 
| Unknown | NULL  | 3     | 2 | NULL | 0x6BE348 | 
| Unknown | 3  | NULL    | 3 | ASD | NULL  | 
| True | 3  | 3     | 4 | ASD | 0x6BE348 | 
+---------+----------+--------------------+----+-------+----------+ 

之所以看到这一点,他们是UNKNOWN是因为LENDATALENGTH都在传递NULL

+0

谢谢!这是原因。 –

+2

极好的例子 – TheGameiswar

Martin Smith的答案已经返回NULL包括为什么SQL服务器被允许的原因在不违反检查约束的情况下指定值。

您可以修改您的检查约束以使其工作。 Demo

CONSTRAINT [CK_Filters_FCode_FVersion] 
     CHECK (([FCode] IS NULL AND [FVersion] IS NULL) 
       OR (LEN(ISNULL([FCode],'')) > 0 
        AND ISNULL(DATALENGTH([FVersion]),-1) > 0))