SQL Server数据库的约束

约束是数据库服务器为您强制的规则。

建立和使用约束的目的是为了保证数据的完整性。

  • PRIMARY KEY 约束
  • FOREIGN KEY 约束
  • UNIQUE 约束
  • CHECK 约束
  • DEFAULT 定义
  • 允许空值

 

强制数据完整性约束

主键PRIMARY KEY——表通常具有包含唯一标识表中每一行的值的一列或一组列。这样的一列或多列称为表的主键 (PK),用于强制表的实体完整性。在创建或修改表时,您可以通过定义 PRIMARY KEY 约束来创建主键。

一个表只能有一个 PRIMARY KEY 约束,并且 PRIMARY KEY 约束中的列不能接受空值。由于 PRIMARY KEY 约束可保证数据的唯一性,因此经常对标识列定义这种约束。

如果为表指定了 PRIMARY KEY 约束,则 SQL Server 2005 Database Engine 将通过为主键列创建唯一索引来强制数据的唯一性。当在查询中使用主键时,此索引还可用来对数据进行快速访问。因此,所选的主键必须遵守创建唯一索引的规则。

如果对多列定义了 PRIMARY KEY 约束,则一列中的值可能会重复,但来自 PRIMARY KEY 约束定义中所有列的任何值组合必须唯一。

如下图所示,Purchasing.ProductVendor 表中的 ProductID VendorID 列构成了针对此表的复合 PRIMARY KEY 约束。这确保了 ProductID VendorID 的组合是唯一的。

当进行联接时,PRIMARY KEY 约束将一个表与另一个表关联。例如,若要确定哪些供应商供应哪些产品,可以在 Purchasing.Vendor 表、Production.Product 表和 Purchasing.ProductVendor 表之间使用一个三向联接。因为 ProductVendor 包含 ProductID VendorID 列,所以可通过与 ProductVendor 的联系来访问 Product 表和 Vendor 表。

 

外键 (FK) 是用于建立和加强两个表数据之间的链接的一列或多列。当创建或修改表时可通过定义 FOREIGN KEY 约束来创建外键。

在外键引用中,当一个表的列被引用作为另一个表的主键值的列时,就在两表之间创建了链接。这个列就成为第二个表的外键。

例如,因为销售订单和销售人员之间存在一种逻辑关系,所以 AdventureWorks 数据库中的 Sales.SalesOrderHeader 表含有一个指向 Sales.SalesPerson 表的链接。SalesOrderHeader 表中的 SalesPersonID 列与 SalesPerson 表中的主键列相对应。SalesOrderHeader 表中的 SalesPersonID 列是指向 SalesPerson 表的外键。

 

FOREIGN KEY 约束并不仅仅可以与另一表的 PRIMARY KEY 约束相链接,它还可以定义为引用另一表的 UNIQUE 约束。FOREIGN KEY 约束可以包含空值,但是,如果任何组合 FOREIGN KEY 约束的列包含空值,则将跳过组成 FOREIGN KEY 约束的所有值的验证。若要确保验证了组合 FOREIGN KEY 约束的所有值,请将所有参与列指定为 NOT NULL

注意:

FOREIGN KEY 约束可以引用同一数据库的表中的列或同一表中的列。这些称为自引用表。例如,请考虑包含三列的一个雇员表:employee_numberemployee_name manager_employee_number。由于经理本身也是雇员,所以从 manager_employee_number 列到 employee_number 列存在外键关系。

引用完整性

尽管 FOREIGN KEY 约束的主要目的是控制可以存储在外键表中的数据,但它还可以控制对主键表中数据的更改。例如,如果在 Sales.SalesPerson 表中删除一个销售人员行,而这个销售人员的 ID Sales.SalesOrderHeader 表中的销售订单使用,则这两个表之间关联的完整性将被破坏;SalesOrderHeader 表中删除的销售人员的销售订单因为与 SalesPerson 表中的数据没有链接而变得孤立了。

FOREIGN KEY 约束防止这种情况的发生。如果主键表中数据的更改使之与外键表中数据的链接失效,则这种更改将无法实现,从而确保了引用完整性。如果试图删除主键表中的行或更改主键值,而该主键值与另一个表的 FOREIGN KEY 约束中的值相对应,则该操作将失败。若要成功更改或删除 FOREIGN KEY 约束的行,必须先在外键表中删除或更改外键数据,这将把外键链接到不同的主键数据上去。

FOREIGN KEY 约束建立索引

由于以下原因,对外键创建索引通常是有用的:

·                      PRIMARY KEY 约束的更改可由相关表中的 FOREIGN KEY 约束检查。

·                      当在查询中组合相关表中的数据时,经常在联接条件中使用外键列,方法是将一个表的 FOREIGN KEY 约束中的列与另一个表中的主键列或唯一键列匹配。索引使 SQL Server 2005 Database Engine 可以在外键表中快速查找相关数据。但是,创建此索引并不是必需的。即使没有对两个相关表定义 PRIMARY KEY FOREIGN KEY 约束,也可以对来自这两个表中的数据进行组合,但两个表间的外键关系说明已用其键作为条件对其进行了优化,以便组合到查询中。有关在联接中使用 FOREIGN KEY 约束的详细信息,请参阅联接基础知识查询类型和索引

表中的 FOREIGN KEY 约束数

SQL Server 对一个表可以包含的 FOREIGN KEY 约束(引用其他表)数没有预定义限制,对引用特定表的其他表所拥有的 FOREIGN KEY 约束数也没有预定义的限制。但是,实际的 FOREIGN KEY 约束数会受到硬件配置以及数据库和应用程序的设计的限制。建议表中包含的 FOREIGN KEY 约束不要超过 253 个,并且引用该表的 FOREIGN KEY 约束也不要超过 253 个。在设计数据库和应用程序时应考虑强制 FOREIGN KEY 约束的开销。

 

UNIQUE 唯一 约束可以确保在非主键列中不输入重复的值。尽管 UNIQUE 约束和 PRIMARY KEY 约束都强制唯一性,但想要强制一列或多列组合(不是主键)的唯一性时应使用 UNIQUE 约束而不是 PRIMARY KEY 约束。

可以对一个表定义多个 UNIQUE 约束,但只能定义一个 PRIMARY KEY 约束。

而且,UNIQUE 约束允许 NULL 值,这一点与 PRIMARY KEY 约束不同。不过,当与参与 UNIQUE 约束的任何值一起使用时,每列只允许一个空值。

FOREIGN KEY 约束可以引用 UNIQUE 约束。

 

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 插入到 MyColumnSQL Server 2005 Database Engine 将插入 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 语句也会成功。

 

DEFAULT 定义 记录中的每列均必须有值,即使该值是 NULL。可能会有这种情况:必须向表中加载一行数据但不知道某一列的值,或该值尚不存在。如果列允许空值,就可以为行加载空值。由于可能不希望有可为空的列,因此最好是为列定义 DEFAULT 定义(如果合适)。例如,通常为数值列指定零作为默认值,为字符串列指定 N/A 作为默认值。

将某行加载到某列具有 DEFAULT 定义的表中时,即隐式指示 SQL Server 2005 Database Engine 将默认值插入到没有指定值的列中。

注意:

您还可以使用 INSERT STATEMENT DEFAULT VALUES 子句显式指示数据库引擎 为列插入默认值。

如果列不允许空值且没有 DEFAULT 定义,就必须为该列显式指定值,否则数据库引擎 会返回错误,指出该列不允许空值。

插入到结合了 DEFAULT 定义和列的为空性所定义的列中的值可归纳如下表中所示。

列定义

无输入,无 DEFAULT 定义

无输入, DEFAULT 定义

输入空值

允许空值

NULL

默认值

NULL

不允许空值

错误

默认值

错误

 

允许空值  列的为空性决定表中的行是否可为该列包含空值。空值(或 NULL)不同于零 (0)、空白或长度为零的字符串(如 "")。NULL 的意思是没有输入。出现 NULL 通常表示值未知或未定义。例如,AdventureWorks 数据库的 Production.Product 表的 SellEndDate 列中的空值不表示商品没有销售结束日期。NULL 表示该日期未知或尚未设置。

注意:

建议避免允许空值,因为空值会使查询和更新变得更复杂,还因为存在不能与可为空的列一起使用的其他列选项,如 PRIMARY KEY 约束。

如果插入一行,但没有为允许空值的列包括值,SQL Server 2005 Database Engine 将提供 NULL 值,除非存在 DEFAULT 定义或 DEFAULT 对象。用关键字 NULL 定义的列也接受用户的 NULL 显式输入,不论它是何种数据类型或是否有默认值与之关联。NULL 值不应放在引号内,否则会被解释为字符串“NULL”而不是空值。

指定某一列不允许空值有助于维护数据的完整性,因为这样可以确保行中的列永远包含数据。如果不允许空值,用户向表中输入数据时必须在列中输入一个值,否则数据库将不接收该表行。

注意:

定义了 PRIMARY KEY 约束或 IDENTITY 属性的列不允许空值。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值