约束
概述
约束(Constraints)是用于限制表中数据的规则,确保数据的完整性和一致性。
安全性约束
完整性约束:确保数据的准确和可靠
实体完整性约束(主键约束)
域完整性约束(数据类型)
引用完整性约束(外键约束)
用户自定义完整性约束(check 约束)
主键约束(PRIMARY KEY)
作用:唯一标识表中的每一行,确保数据的唯一性
基本特性
- 唯一性:关系中任意元组的主键值必须唯一
- 主键列的值必须唯一且不能为
NULL
。 - 一个表只能有一个主键,但主键可以由多个列组成(复合主键)。
- 关系中任意元组的主键值必须唯一(unique)
- 主键列的值必须唯一且不能为
- 非空性:关系中任意元组在主键值必须非空
- 关系中任意元组在主键值必须非空(not null)
- 不可更改性:主键值一旦设定,通常不应修改
1 | -- 创建表时指定主键 |
主键选择策略
- 自然主键:使用业务中有意义的字段(如身份证号)
- 代理主键:使用无意义的自增ID(推荐)
- 复合主键:多个字段组合作为主键
域完整性约束
规则:关系中某属性取值必须在合法的范围内
实现:
一般通过数据类型来实现域完整性约束。不同的数据类型限制了属性可以接受的值的类型和范围。
1
2
3
4CREATE TABLE products (
price DECIMAL(10,2) NOT NULL, -- 价格必须为数字
in_stock BOOLEAN DEFAULT TRUE -- 布尔类型约束
);用户自定义完整性约束。
1
2
3
4CREATE TABLE employees (
age INT CHECK (age >= 18 AND age <= 65),
email VARCHAR(100) CHECK (email LIKE '%@%.%')
);为列设置默认值,当插入数据时如果没有指定该列的值,数据库将自动使用默认值。
ENUM 类型
1
2
3CREATE TABLE orders (
status ENUM('pending', 'processing', 'shipped', 'delivered') DEFAULT 'pending'
);
作用:用于确保表中列(属性)取值有效性和正确性的一种机制
唯一约束(UNIQUE)
- 作用:确保列中的值唯一,但允许
NULL
值。 - 特点:
- 一个表可以有多个唯一约束。
- 唯一约束可以作用于单列或多列(复合唯一约束)。
与主键的区别
特性 | 主键约束 | 唯一约束 |
---|---|---|
NULL值 | 不允许 | 允许(但只能有一个NULL) |
数量 | 每表一个 | 每表多个 |
索引类型 | 聚集索引 | 非聚集索引 |
1 | CREATE TABLE users ( |
非空约束(NOT NULL)**
- 作用:确保列中的值不能为
NULL
。 - 特点:
- 非空约束只能作用于单列。
1 | -- 创建表时指定 |
默认约束(DEFAULT)
- 作用:为列设置默认值,当插入数据时未指定该列的值时,使用默认值。
- 特点:
- 默认值可以是常量、表达式或函数。
常用默认值:
1 | CREATE TABLE logs ( |
动态默认值:
1 | -- 使用函数作为默认值 |
外键约束(FOREIGN KEY)
- 作用:确保表之间的引用完整性,用于关联两个表。
- 规则:设F是关系R的外键,则R中任意元组的F属性值必须满足:F 为空或F不为空,其值必须在 S 中存在
- 特点:
- 外键列的值必须存在于被引用表的主键或唯一键中。
- 外键可以为
NULL
。
完整语法
1 | CREATE TABLE child_table ( |
检查约束(CHECK)
- 作用:确保列中的值满足指定条件。
- 特点:
- MySQL 8.0.16 及以上版本支持
CHECK
约束。 - 条件可以是逻辑表达式。
- MySQL 8.0.16 及以上版本支持
1 | CREATE TABLE employees ( |
动递增约束(AUTO_INCREMENT)
作用:自动为列生成唯一的递增值,通常用于主键列。
特点:
只能用于整数类型的列。
每个表只能有一个
AUTO_INCREMENT
列。
复合约束
- 作用:将多个列组合在一起作为约束条件。
- 常见类型:
- 复合主键:多个列共同作为主键。
- 复合唯一约束:多个列共同确保唯一性。
1 | CREATE TABLE orders( |
约束操作
约束的添加
1 | ALTER TABLE 表名 ADD CONSTRAINT 约束名 约束类型 (列名); |
约束的删除
1 | ALTER TABLE 表名 DROP CONSTRAINT 约束名; |
约束的命名
1 | CREATE TABLE 表名 ( |
查看约束
1 | -- 从information_schema.TABLE_CONSTRAINTS系统表中获取信息 |
修改约束
1 | -- 修改检查约束(MySQL中需要先删除再添加) |
约束演示
1 | -- 约束建表 |
外键约束
添加外键
1 | CREATE TABLE 表名( |
示例
1 | CREATE TABLE customers ( |
外键约束的级联操作
可以通过 ON DELETE
和 ON UPDATE
子句定义外键的级联行为。例如:
ON DELETE CASCADE
:当主表中的记录被删除时,自动删除从表中的相关记录。ON UPDATE CASCADE
:当主表中的记录被更新时,自动更新从表中的相关记录。
示例:使用
ON DELETE CASCADE
1 | CREATE TABLE orders ( |
测试:
删除
customers
表中的一条记录:1
DELETE FROM customers WHERE id = 1;
检查
orders
表:1
SELECT * FROM orders;
结果:
customer_id
为 1 的订单也会被自动删除。
外键约束的删除和更新行为
NO ACTION
: 父表中删除/更新对应记录时,先检查该记录是否有对应外键,有则不允许删除/更新RESTRICT
:父表中删除/更新对应记录时,先检查该记录是否有对应外键,有则不允许删除/更新NO ACTION/RESTRICT(默认)会阻止执行会破坏引用完整性的操作
CASCADE
父表中删除/更新对应记录时,先检查该记录是否有对应外键,有则也删除/更新外键在子表中的记录SET BULL
父表中删除/更新对应记录时,先检查该记录是否有对应外键,有则设置子表中该外键值为null(外键允许null)SET DEFAULT
:父表变更的时候,子表将外键设置成一个默认的值NO ACTION
和RESTRICT
是默认的
如何设置
1 | ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN (外键字段) REFERENCES 主表名 (主表字段名) ON UPDATE CASCADE ON DELETE CASCADE; |
约束实践
学校管理系统约束
students
表:用于存储学生的基本信息,如学生编号、姓名、出生日期、所属专业编号等。学校可以通过该表管理学生档案,了解学生基本情况。courses
表:用于记录课程相关信息,包括课程代码、课程名称、学分、所属系部编号等。学校利用此表进行课程管理,如排课、课程信息维护等。enrollments
表:用于记录学生的选课情况,包括选课记录编号、学生编号、课程代码、学期、成绩等。通过该表可以了解学生的选课动态,统计课程选修人数,核算学生成绩等。
mysql语句:
1 | CREATE TABLE students ( |
student_id
列:数据类型为CHAR(10)
,作为学生的唯一标识。设置为主键,同时通过CHECK
约束确保其值符合正则表达式^[A-Z]{2}[0-9]{8}$
,即学生编号必须是 2 个大写字母开头,后面跟着 8 位数字。name
列:数据类型为VARCHAR(100)
,用于存储学生姓名,NOT NULL
约束表示该字段不能为空。birth_date
列:数据类型为DATE
,用于记录学生出生日期,NOT NULL
约束要求不能为空。CHECK
约束限定出生日期必须是当前日期往前推至少 16 年以前,确保录入的出生日期符合正常入学年龄逻辑。major_id
列:数据类型为INT
,用于存储学生所属专业的编号。通过FOREIGN KEY
约束引用majors
表中的major_id
,建立与专业表的关联关系,保证学生所属专业编号在专业表中存在。
1 | CREATE TABLE courses ( |
course_code
列:数据类型为VARCHAR(10)
,作为课程的唯一标识,设置为主键。title
列:数据类型为VARCHAR(100)
,用于存储课程名称,NOT NULL
约束表示不能为空。credit
列:数据类型为TINYINT
,用于记录课程学分,NOT NULL
约束要求不能为空。CHECK
约束限定学分在 1 到 5 之间,符合常见课程学分设置范围。department_id
列:数据类型为INT
,用于存储课程所属系部的编号,NOT NULL
约束表示不能为空。通过FOREIGN KEY
约束引用departments
表中的department_id
,建立与系部表的关联,保证课程所属系部编号在系部表中存在。
1 | CREATE TABLE enrollments ( |
enrollment_id
列:数据类型为INT
,设置为自增长(AUTO_INCREMENT
),作为选课记录的唯一标识,是该表的主键。student_id
列:数据类型为CHAR(10)
,用于记录选课学生的编号,NOT NULL
约束表示不能为空。通过FOREIGN KEY
约束引用students
表中的student_id
,确保选课学生编号在学生表中存在。course_code
列:数据类型为VARCHAR(10)
,用于记录所选课程的代码,NOT NULL
约束表示不能为空。通过FOREIGN KEY
约束引用courses
表中的course_code
,保证所选课程代码在课程表中存在。semester
列:数据类型为VARCHAR(20)
,用于记录选课的学期,NOT NULL
约束表示不能为空。grade
列:数据类型为CHAR(2)
,用于记录学生该课程的成绩。CHECK
约束限定成绩只能是'A'
、'B'
、'C'
、'D'
、'F'
或空值,符合常见成绩记录规则。UNIQUE KEY (student_id, course_code, semester)
:组合唯一键约束,确保每个学生在每个学期对每门课程的选课记录唯一,防止重复选课记录出现。