check约束(备忘录)

来源:互联网 发布:波粒二象性知乎 编辑:程序博客网 时间:2024/04/30 13:26

 

通过限制列可接受的值,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 列中还有一个两个字符的值。这使得在一个位置可以同时检查多个条件。

ms188258.Caution(zh-cn,SQL.100).gif注意:包括隐式或显式数据类型转换的约束可能会导致某些操作失败。例如,为表定义的作为分区切换的源的此类约束可能会导致 ALTER TABLE...SWITCH 操作失败。在约束定义中避免数据类型转换。

 

CHECK 约束的限制

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

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

CREATE TABLE CheckTbl (col1 int, col2 int);GOCREATE FUNCTION CheckFnctn()RETURNS intAS BEGIN   DECLARE @retval int   SELECT @retval = COUNT(*) FROM CheckTbl   RETURN @retvalEND;GOALTER TABLE CheckTblADD CONSTRAINT chkRowCount CHECK (dbo.CheckFnctn() >= 1 );GO

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

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

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

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

 

使用 WITH NOCHECK 强制执行 CHECK 约束

向现有表中添加 CHECK 约束后,CHECK 约束可以仅应用于新数据,也可以应用于现有数据。默认情况下,CHECK 约束同时应用于现有数据和所有新数据。使用 ALTER TABLE 语句的 WITH NOCHECK 选项可以将新约束仅应用于新添加的数据。如果现有数据已符合新的 CHECK 约束时,或业务规则要求仅从此开始强制约束时,则可以使用此选项。

例如,旧约束可能要求将邮政编码限制为 5 位数字,而新约束要求 9 位数字的邮政编码。5 位数字的旧邮政编码数据依然有效,并且将与 9 位数字的新邮政编码数据共存。因此,只须按新的约束对新邮政编码进行检查。

但是,添加约束但不检查现有数据时应谨慎,因为这样会跳过 数据库引擎中用于强制表的完整性规则的控制。

原创粉丝点击