深入理解 MySQL 数据表约束机制与应用
在关系型数据库中,约束(Constraint)是确保数据完整性与有效性的核心机制。通过在表结构上施加限制条件,数据库管理系统能够自动拦截不符合业务规则的脏数据。
约束的主要分类
在 MySQL 中,常用的约束类型包括以下几种:
- 非空约束(NOT NULL):强制字段值不能为空。
- 唯一约束(UNIQUE):确保字段或字段组合的值在表中不重复。
- 主键约束(PRIMARY KEY):唯一标识表中的每一行记录,兼具非空和唯一特性。
- 外键约束(FOREIGN KEY):维护表与表之间的参照完整性。
- 检查约束(CHECK):限制字段值必须满足指定的布尔表达式。注:早期版本的 MySQL 会忽略 CHECK 约束,但从 MySQL 8.0.16 开始,CHECK 约束已被正式支持并强制执行。
非空约束(NOT NULL)
非空约束用于保证某列在插入或更新时必须有明确的值,不允许使用 NULL。这在处理核心业务字段(如用户名、订单号)时非常关键。
CREATE TABLE sys_employee (
emp_id INT,
emp_name VARCHAR(50) NOT NULL,
hire_date DATE NOT NULL
);
唯一约束(UNIQUE)
唯一约束确保指定列的值在整个表中是独一无二的。与主键不同,唯一约束允许存在 NULL 值(在 MySQL 中,允许多个 NULL 值同时存在而不触发唯一性冲突)。
1. 列级唯一约束
直接在字段定义后追加 UNIQUE 关键字,适用于单列去重。
CREATE TABLE sys_employee (
emp_id INT,
emp_name VARCHAR(50) NOT NULL,
id_card_number VARCHAR(18) UNIQUE
);
2. 表级联合唯一约束
当需要确保多个字段的组合不重复时(例如同一个部门下的员工编号不能重复),可以在表定义的末尾使用表级约束。
CREATE TABLE sys_employee (
emp_id INT,
dept_id INT,
emp_code VARCHAR(20),
UNIQUE KEY uk_dept_emp_code (dept_id, emp_code)
);
3. 自定义约束名称
为约束显式命名是一个良好的工程实践,这使得后续通过 ALTER TABLE 修改或删除约束时更加方便。
CREATE TABLE sys_employee (
emp_id INT,
work_email VARCHAR(100),
CONSTRAINT chk_unique_work_email UNIQUE (work_email)
);
主键约束(PRIMARY KEY)
主键是表中记录的"身份证",用于唯一标识每一行数据。一个设计良好的关系表必须拥有主键。即使两行记录的业务数据完全相同,只要主键不同,它们在物理和逻辑上就是两条独立的记录。
1. 单列主键
最常见的形式,通常使用自增整数或分布式 ID 作为单一主键。
CREATE TABLE sys_department (
dept_id INT PRIMARY KEY,
dept_name VARCHAR(100) NOT NULL
);
2. 复合主键
当单一字段无法唯一标识记录时,可以将多个字段组合作为主键。复合主键必须在表级进行定义。
CREATE TABLE sys_emp_role (
emp_id INT,
role_id INT,
assign_date DATE,
PRIMARY KEY (emp_id, role_id)
);
主键与 NOT NULL + UNIQUE 的本质差异
从数据校验的表象来看,为字段同时添加 NOT NULL 和 UNIQUE 约束,其效果与 PRIMARY KEY 完全一致:既不能为空,也不能重复。然而,在 MySQL 的 InnoDB 存储引擎底层,两者存在本质区别:
- 索引结构:主键会自动创建聚簇索引(Clustered Index),表中的数据行物理存储顺序与主键顺序一致,直接决定了数据的检索效率。而
UNIQUE约束创建的是二级唯一索引(Secondary Unique Index)。 - 数量限制:一张表只能有一个主键,但可以拥有多个
UNIQUE约束。 - NULL 值处理:主键绝对不允许
NULL,而UNIQUE字段在 MySQL 中允许包含NULL值。
