1

当我使用下面的测试脚本创建检查约束时,仍然允许违反约束的数据进入表,并且约束仍然显示为受信任。

我意识到检查约束没有正确检查 NULL(它包括column = null而不是column IS null),但我仍然希望 SQL Server 不允许“ASDF”、“3”或 NULL 值,因为检查条件评估为 false反对这些价值观。有人可以解释为什么这个检查约束允许以下值:NULL、'3'、'ASDF'?

如果我将约束条件更改为(checkMe is null or checkMe = '1' or checkMe = '2'),则它按预期工作。

SQL Server 版本:Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64)

CREATE TABLE dbo.testCheck(checkMe varchar(50));
go

向表中插入数据

INSERT INTO dbo.testCheck(checkMe)
VALUES ('1'),('2'),(NULL),('3');
GO

添加约束,检查以便检查现有数据。我希望 NULL 和 '3' 都违反了这个检查,但它以某种方式成功了。

ALTER TABLE dbo.testCheck WITH CHECK 
ADD CONSTRAINT ck_testCheck 
CHECK (checkMe = null or checkMe = '1' or checkMe = '2');
GO

添加检查约束后尝试插入无效数据...成功了吗?

INSERT INTO dbo.testCheck(checkMe) VALUES('ASDF');
GO

显示表包含无效数据,并且此约束被标记为受信任,这意味着表中的所有数据都已针对约束进行了验证

SELECT *
    --this is the same logic as in the check constraint, shows 3 rows that do not pass
    , checkConstraintLogic = case when (checkMe = null or checkMe = '1' or checkMe = '2') then 'PASS' else 'FAIL' end
FROM dbo.testCheck;
go

SELECT parentObject = isnull(OBJECT_SCHEMA_NAME(k.parent_object_id) + '.', '') + OBJECT_NAME(k.parent_object_id)
    , k.name, k.is_not_trusted
FROM sys.check_constraints k 
WHERE k.parent_object_id = object_id('dbo.testCheck')
ORDER BY 1;
GO

脚本输出:

输出截图

4

2 回答 2

2

检查约束与 WHERE 子句的不同之处在于,如果表达式计算结果为空标记,则 CHECK 允许修改。澄清:WHERE 子句过滤掉表达式计算结果为falsenull 标记的行;Check 约束仅过滤掉评估为false的修改。

您编写的表达式总是计算为 null,因为它内部有一个与 null 的比较。更改= nullis null

此外,检查约束的不同用法对 CHECK/NOCHECK 有不同的默认值,因此您应该养成始终指定它的习惯。

试试下面的。

ALTER TABLE dbo.testCheck WITH CHECK 
WITH CHECK
ADD CONSTRAINT ck_testCheck 
CHECK (checkMe IS null or checkMe = '1' or checkMe = '2');

编辑:关于“但我想知道为什么这个示例的计算结果为 True”,正如您所计算的那样,您的示例计算结果不是true而是null 标记,这是 Check 约束允许的。对不起,我应该解释得更好一点。

于 2014-04-10T21:11:48.827 回答
0

如此处指定:

CHECK 约束拒绝评估为 FALSE 的值。

换句话说:

当它检查的条件对于表中的任何行都不是 FALSE 时,CHECK 约束返回 TRUE。

在您的情况下,表达式的(checkMe is null or checkMe = '1' or checkMe = '2')计算结果为 NULL(又名 Unknown),并且 CHECK 约束返回 TRUE(因为它正在检查的条件不是 FALSE)

来自同一来源的一个很好的例子:

例如,假设您在 int 列 MyColumn 上放置一个约束,指定 MyColumn 只能包含值 10 (MyColumn = 10)。如果将值 NULL 插入 MyColumn,数据库引擎将插入 NULL 并且不返回错误。

于 2014-04-10T21:34:48.430 回答