UNIQUE 约束和 CHECK 约束

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

UNIQUE 约束和 CHECK 约束是可用于在 SQL Server 表中强制实施数据完整性的两种约束类型。 这些是重要的数据库对象。

本文包含以下各节。

UNIQUE 约束

约束是 SQL Server 数据库引擎为你强制执行的规则。 例如,您可以使用 UNIQUE 约束确保在非主键的特定列中不会输入重复的值。 尽管 UNIQUE 约束和 PRIMARY KEY 约束都强制实施唯一性,但如果要在非主键的一列(或多列组合)中强制实施唯一性,则应使用 UNIQUE 约束而不是 PRIMARY KEY 约束。

PRIMARY KEY 约束不同的是,UNIQUE 约束允许 NULL 值。 不过,当与参与 UNIQUE 约束的任何值一起使用时,每列只允许一个空值。 UNIQUE 约束可以由 FOREIGN KEY 约束引用。

默认情况下,向表中的现有列添加 UNIQUE 约束后,数据库引擎将检查列中的现有数据,以确保所有值都是唯一的。 如果向含有重复值的列添加 UNIQUE 约束,数据库引擎将返回错误消息,并且不会添加该约束。

数据库引擎将自动创建 UNIQUE 索引来强制实施 UNIQUE 约束的唯一性要求。 因此,如果尝试插入重复的行,数据库引擎将返回错误消息,说明该操作违反了 UNIQUE 约束,并且不会将该行添加到表中。 除非显式指定了聚集索引,否则默认情况下将创建唯一的非聚集索引来强制执行 UNIQUE 约束。

CHECK 约束

CHECK 约束通过限制一个或多个列可接受的值来强制实施域完整性。 可以通过任何基于逻辑运算符返回 TRUEFALSE 的逻辑(布尔)表达式创建 CHECK 约束。 例如,可以通过创建 CHECK 约束将 salary 列中值的范围限制为从 $15,000 到 $100,000 之间的数据。 这可防止薪金超出常规薪金范围之外。 逻辑表达式将如下: salary >= 15000 AND salary <= 100000

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

CHECK 约束类似于 FOREIGN KEY 约束,因为可以控制放入列中的值。 但两者在确定有效值的方式上有所不同:FOREIGN KEY 约束从其他表获得有效值列表,而 CHECK 约束通过逻辑表达式确定有效值。

注意

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

CHECK 约束的限制

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

如果 CHECK 约束检查的条件对于表中的任何行都不是 FALSE,则将返回 TRUECHECK 约束在行级执行。 如果创建的表没有任何行,则该表的任何 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;

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

注意

如果表是为复制发布的,则必须使用 Transact-SQL 语句 ALTER TABLE 或 SQL Server 管理对象 (SMO) 对架构进行更改。 使用表设计器或数据库关系图设计器更改架构后,会尝试删除并重新创建表。 由于您不能删除已发布的对象,因此架构更改将失败。

任务 文章
介绍如何创建唯一约束。 创建 UNIQUE 约束
介绍如何修改唯一约束。 修改唯一约束
介绍如何删除唯一约束。 删除唯一约束
介绍如何创建 CHECK 约束。 创建 CHECK 约束
介绍当复制代理在表中插入或更新数据时如何禁用 CHECK 约束。 对复制禁用 CHECK 约束
介绍在表中添加、更新或删除数据时如何禁用 CHECK 约束。 对 INSERT 和 UPDATE 语句禁用 CHECK 约束
介绍如何更改约束表达式或更改对特定条件启用或禁用约束的选项。 修改 CHECK 约束
介绍如何删除 CHECK 约束。 删除 CHECK 约束
介绍如何查看 CHECK 约束的属性。 唯一约束和 CHECK 约束