CHECK 约束

通过限制列可接受的值,CHECK 约束可以强制域的完整性。此类约束类似于 FOREIGN KEY 约束,因为可以控制放入列中的值。但是,它们在确定有效值的方式上有所不同:FOREIGN KEY 约束从其他表获得有效值列表,而 CHECK 约束通过不基于其他列中的数据的逻辑表达式确定有效值。例如,可以通过创建 CHECK 约束将 salary 列中值的范围限制为从 $15,000 到 $100,000 之间的数据。这将防止输入的薪金值超出正常的薪金范围。

可以通过任何基于逻辑运算符返回 TRUE 或 FALSE 的逻辑(布尔)表达式创建 CHECK 约束。对于上面的示例,逻辑表达式为:salary >= 15000 AND salary <= 100000。

可以将多个 CHECK 约束应用于单个列。还可以通过在表级创建 CHECK 约束,将一个 CHECK 约束应用于多个列。例如,多列 CHECK 约束可用于确认 country/region 列值为 USA 的任意行是否在 state 列中还有一个两个字符的值。这使得在一个位置可以同时检查多个条件。

注意事项注意

包括隐式或显式数据类型转换的约束可能会导致某些操作失败。例如,为表定义的作为分区切换的源的此类约束可能会导致 ALTER TABLE...SWITCH 操作失败。在约束定义中避免数据类型转换。

CHECK 约束的限制

CHECK 约束不接受计算结果为 FALSE 的值。因为空值的计算结果为 UNKNOWN,所以表达式中存在这些值可能会覆盖约束。例如,假设对 int 列 MyColumn 应用一个约束,指定 MyColumn 只能包含值 10(即 MyColumn=10)。如果将值 NULL 插入到 MyColumn,数据库引擎将插入 NULL 且不返回错误。

如果 CHECK 约束检查的条件对于表中的任何行都不是 FALSE,它将返回 TRUE。如果刚创建的表没有任何行,则此表的任何 CHECK 约束都视为有效。这种情况可能会产生意外结果,如下面的示例所示。

CREATE TABLE CheckTbl (col1 int, col2 int);
GO
CREATE FUNCTION CheckFnctn()
RETURNS int
AS 
BEGIN
   DECLARE @retval int
   SELECT @retval = COUNT(*) FROM CheckTbl
   RETURN @retval
END;
GO
ALTER TABLE CheckTbl
ADD CONSTRAINT chkRowCount CHECK (dbo.CheckFnctn() >= 1 );
GO

添加的 CHECK 约束指定表 CheckTbl 必须至少包含一行。但是,因为表中不包含任何可供检查此约束的条件的行,所以 ALTER TABLE 语句将成功。

执行 DELETE 语句时不验证 CHECK 约束。因此,使用特定类型的 CHECK 约束对表执行 DELETE 语句时可能会产生意外结果。例如,假设对表 CheckTbl 执行下列语句。

INSERT INTO CheckTbl VALUES (10, 10)
GO
DELETE CheckTbl WHERE col1 = 10;

即使 CHECK 约束指定表 CheckTbl 必须至少包含 1 行,DELETE 语句也会成功。