sql-server - 检查约束在 SQL Server 2016 中不起作用

标签 sql-server tsql constraints

下面有一个简单的例子

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

你可以看到这个

SELECT CASE
         WHEN( ( [FCode] IS NULL
                 AND [FVersion] IS NULL )
                OR ( LEN([FCode]) > 0
                     AND DATALENGTH([FVersion]) > 0 ) ) THEN 'True'
         WHEN NOT ( ( [FCode] IS NULL
                      AND [FVersion] IS NULL )
                     OR ( LEN([FCode]) > 0
                          AND DATALENGTH([FVersion]) > 0 ) ) THEN 'False'
         ELSE 'Unknown'
       END                    AS [check],
       LEN([FCode])           AS LenFCode,
       DATALENGTH([FVersion]) AS DataLengthFVersion,
       *
FROM   [dbo].[filters] 

哪个返回

+---------+----------+--------------------+----+-------+----------+
|  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 时都返回 NULL

关于sql-server - 检查约束在 SQL Server 2016 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45560615/

相关文章:

sql - 如何在 SQL PIVOT 中 ORDER BY

sql-server - 在TSQL中,如何按 "most occurring"值排序?

sql - Order - OrderDetail 在不使用 Cursor 的情况下获取结果集

SQL结合Union和Except

sql - 从行中获取逗号分隔的字符串

Swift - 以编程方式更改约束

ios - 切换到横向时,Tableview 将约束更改为全屏

sql - Entity Framework : How to properly handle exceptions that occur due to SQL constraints

sql-server - 如何查询包含方括号的表?

java - Android:HttpPost - 尝试将用户输入的数据插入到服务器上的 SQL 表中