介绍
在设计数据库时,有时您可能需要对某些列中允许的数据进行限制。例如,如果您要创建一个存储摩天大楼信息的表,您可能希望存储每栋建筑物高度的列不允许出现负值。.
关系数据库管理系统 (RDBMS) 允许您使用约束来控制添加到表中的数据。约束是一种特殊规则,它适用于一个或多个列(或整个表),并通过语句限制对表数据所做的更改。 插入, 更新, 或者 删除 它有限制。.
本文详细探讨了约束的定义及其在关系数据库管理系统(RDBMS)中的应用。此外,本文还逐一介绍了SQL标准中定义的五种约束,并解释了相应的函数。.
有哪些局限性?
在 SQL 中,约束是指应用于列或表的任何规则,用于限制可以插入到其中的数据。每当您尝试执行更改表中存储的数据的操作(例如 INSERT、UPDATE 或 DELETE 语句)时,关系数据库管理系统 (RDBMS) 都会检查该数据是否违反了现有约束,如果违反,则会返回错误。.
数据库管理员通常依靠约束来确保数据库遵循一组预定义的业务规则。在数据库的上下文中,业务规则是指企业或其他组织遵循的任何策略或流程,其数据必须遵守这些策略或流程。例如,假设您正在构建一个用于记录客户商店库存的数据库。如果客户指定每个产品记录必须具有唯一的标识号,您可以创建一个带有唯一约束的列,以确保该列中没有两个条目是相同的。.
约束对于维护数据完整性也十分有用。数据完整性是一个宽泛的概念,通常用来描述数据库中数据的整体准确性、一致性和合理性,并根据其具体应用场景进行定义。数据库中的表通常相互关联,一个表中的列依赖于另一个表中的值。由于数据录入常常容易出现人为错误,约束在这种情况下就显得尤为重要,因为它们可以确保任何错误录入的数据都不会影响这些关联关系,从而避免损害数据库数据的完整性。.
假设您正在设计一个包含两个表的数据库:一个表用于列出学校的在校学生,另一个表用于列出该校篮球队的成员。您可以对篮球队表中的某一列应用外键约束,使其引用学校表中的某一列。这样就建立了两个表之间的关系,要求球队表中的每个条目都必须引用学生表中的某个条目。.
用户在首次创建表时定义约束,也可以稍后使用 ALTER TABLE 语句添加约束,前提是这些约束不与表中已有的数据冲突。创建约束时,数据库系统会自动为其生成一个名称,但在大多数 SQL 实现中,您可以为每个约束添加自定义名称。这些名称用于在修改或删除约束时,通过 ALTER TABLE 语句引用这些约束。.
SQL 标准正式定义了五种约束:
- 主键
- 外键
- 独特的
- 审查
- 它不是空的。
现在你已经对约束的使用有了大致的了解,让我们仔细看看这五个约束中的每一个。.
主键
主键约束要求给定列中的每个条目都是唯一的且不能为 NULL,从而允许您使用该列来标识表中的每一行。.
在关系模型中,键是指表中的一列或一组列,其中每个值都保证唯一且不包含 NULL 值。主键是一种特殊的键,其值用于标识表中的每一行,而构成主键的列也可以用于在数据库的其他部分标识该表。.
这是关系型数据库的一个重要特性:有了主键,用户无需知道数据实际存储在哪台机器上,数据库管理系统(DBMS)就能跟踪每条记录并按需检索。这意味着记录没有固定的逻辑顺序,用户可以按照任意顺序或通过任意筛选条件检索数据。.
在 SQL 中,您可以使用 PRIMARY KEY 约束创建主键,它本质上是 UNIQUE 约束和 NOT NULL 约束的组合。定义主键后,数据库管理系统 (DBMS) 会自动创建一个与其关联的索引。索引是一种数据库结构,有助于更快地从表中检索数据。就像教科书中的索引一样,查询只需检查索引列中的条目即可找到相关值。这使得主键能够作为表中每一行的标识符。.
一个表只能有一个主键,但与普通键一样,主键可以由多个列组成。也就是说,主键的一个显著特征是,它们只使用唯一标识表中每一行所需的最小属性集。为了说明这一点,假设有一个表,它使用以下三列存储学校学生的信息:
学生证用于存储每个学生的唯一识别号码名用于记录每个学生的名字姓用于记录每位学生的姓氏
学校里可能存在一些学生同名的情况,因此“firstName”列不适合用作主键。同样的情况也适用于“lastName”列。虽然同时包含“firstName”和“lastName”列的主键或许可行,但仍然存在两个学生同名同姓的可能性。.
由学生ID和名字或姓氏列组成的主键或许可行,但由于每个学生的ID号都是唯一的,因此在主键中包含每个姓名列是多余的。所以,在这种情况下,能够识别每一行的最小属性集,也就是作为表主键的理想选择,就是学生ID列。.
如果键由可观察、可用的数据构成(即代表现实世界实体、事件或属性的数据),则称为自然键。如果键是内部生成的,不代表数据库外部的任何事物,则称为代理键或人工键。一些数据库系统不建议使用自然键,因为即使看似固定的数据点也可能以不可预测的方式发生变化。.
外键
外键约束要求给定列中的每个条目必须已存在于另一个表的特定列中。.
如果要建立两个表之间的关联,一种方法是定义一个带有外键约束的外键。外键是指一个表(“子表”)中的一列,其值来自另一个表(“父表”)中的某个键。这是一种表达两个表之间关系的方式:外键约束要求它所指向的列中的值必须存在于它所引用的列中。.
下图展示了两个表之间的关系:一个表用于记录公司员工信息,另一个表用于跟踪公司销售情况。在本例中,员工表的主键被销售表的外键引用:
如果尝试向子表中插入一条记录,但外键列中输入的值在父表的主键中不存在,则插入语句无效。这有助于维护关系级别的完整性,因为两个表中的行始终正确关联。.
通常情况下,子表的外键是其父表的主键,但这并非总是如此。在大多数关系型数据库管理系统(RDBMS)中,父表中任何具有唯一键(UNIQUE)或主键(PRIMARY KEY)约束的列都可以被子表的外键引用。.
独特的
UNIQUE 约束可防止将任何重复值添加到给定列中。.
顾名思义,唯一约束要求给定列中的每个条目都必须是唯一值。任何尝试添加已存在于该列中的值的操作都会导致错误。.
UNIQUE 约束对于强制表之间建立一对一关系非常有用。如前所述,您可以使用外键在两个表之间建立关系,但表之间可以存在多种类型的关系:
如果父表中的行与子表中的唯一一行相对应,则称这两个表具有一对一关系。.یک به یک一对多在多对一的关系中,父表中的一行可以与子表中的多行相关联,但子表中的每一行只能与父表中的一行相关联。.多少?如果父表中的行可以与子表中的多行相关联,反之亦然,则称两者具有多对多关系。.
通过向应用了外键约束的列添加唯一约束,可以确保父表中的每个条目在子表中只出现一次,从而在两个表之间建立一对一的关系。.
请注意,您可以在表级别和列级别定义 UNIQUE 约束。在表级别定义时,UNIQUE 约束可以应用于多个列。在这种情况下,约束中的每个列都可以有重复值,但每一行在受约束列中的值组合必须是唯一的。.
审查
CHECK 约束定义了列的条件(称为谓词),输入到该列中的任何值都必须满足该条件。.
CHECK 约束谓词编写成一个表达式,其计算结果可能为 TRUE、FALSE 或未知。如果您尝试在 CHECK 约束中输入一个值,并且该值导致语句的计算结果为 TRUE 或未知(NULL 值会导致这种情况),则操作将成功。但是,如果表达式的计算结果为 FALSE,则操作将失败。.
CHECK 谓词通常依赖于数学比较运算符(例如 <、>、<=、OR >=)来限制给定列中允许的数据范围。例如,CHECK 约束的一个常见用途是防止某些列中出现负值,因为在某些情况下,负值是不合理的,如下例所示。.
这条 CREATE TABLE 语句创建了一个名为 productInfo 的表,其中包含名称、ID 号和价格三列,分别存储每个产品的名称、ID 号和价格。由于产品价格不可能为负数,因此该语句对价格列应用了 CHECK 约束,以确保其值均为正数:
CREATE TABLE productInfo (
productID int,
name varchar(30),
price decimal(4,2)
CHECK (price > 0)
);每个 CHECK 谓词都不能使用数学比较运算符。通常,您可以在 CHECK 谓词中使用任何可以计算结果为 true、false 或 unknown 的 SQL 运算符,包括 LIKE、BETWEEN、IS NOT NULL 等。某些 SQL 实现(但并非所有实现)甚至允许您在 CHECK 谓词中包含子查询。但是请注意,大多数实现不允许您在语句中引用另一个表。.
它不是空的。
NOT NULL 约束可防止将任何 NULL 值添加到给定列中。.
在大多数 SQL 实现中,如果您插入一行数据但没有为特定列指定值,数据库系统默认会将缺失的数据表示为 NULL。在 SQL 中,NULL 是一个特殊的关键字,用于表示未知、缺失或未指定的值。但是,NULL 本身并不是一个值,而是一种未知值的状态。.
为了说明这种区别,假设有一个用于跟踪艺人经纪公司客户的表格,其中包含每个客户的姓名(包括名字和姓氏)。如果客户使用单个名字,例如“Cher”、“Usher”或“Beyoncé”,数据库管理员可能只会在名字列中输入一个名字,这会导致数据库管理系统(DBMS)在姓氏列中插入 NULL 值。数据库并非真的将客户的姓氏视为“空值”,而只是表示该行姓氏列的值未知,或者该字段不适用于该特定记录。.
顾名思义,NOT NULL 约束会阻止指定列中的任何值为 NULL。这意味着,对于任何带有 NOT NULL 约束的列,在插入新行时必须为其指定一个值。否则,INSERT 操作将失败。.
结果
对于任何希望设计具有高数据完整性和安全性的数据库的人来说,约束都是必不可少的工具。通过限制输入到列中的数据,您可以确保表之间的关系得到正确维护,并且数据库遵循定义其用途的业务规则。.










