在数据库中,约束(Constraint)是用来限制数据合法性的手段,UNIQUE
只是其中一种。MySQL 及其他关系型数据库还支持以下几种常见约束类型:
🔒 常见的约束类型汇总
约束类型 | 关键字 | 保证 | 示例 | 用途描述 |
---|---|---|---|---|
✅ 主键约束 | PRIMARY KEY | 唯一 + 非空,每表仅一个 | id INT PRIMARY KEY | 唯一标识每一行,不能为 NULL |
✅ 唯一约束 | UNIQUE | 值唯一,允许多个NULL | email VARCHAR(100) UNIQUE | 限制字段值不能重复,可为 NULL |
✅ 非空约束 | NOT NULL | 非空 | name VARCHAR(50) NOT NULL | 限制字段值不能为 NULL |
✅ 默认值约束 | DEFAULT | 默认值 | status VARCHAR(10) DEFAULT 'active' | 设置字段的默认值 |
✅ 外键约束 | FOREIGN KEY | 关联父表字段,保证数据合法性 | FOREIGN KEY (x) REFERENCES y(z) | 建立两个表之间的关联关系 |
✅ 检查约束(MySQL 8+) | CHECK | 条件约束 | age INT CHECK (age > 0) | 限制字段必须满足某种条件(如值范围) |
🧠 示例综合建表语句:
sql
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
age INT CHECK (age >= 0 AND age <= 120),
status VARCHAR(10) DEFAULT 'active',
class_id INT,
FOREIGN KEY (class_id) REFERENCES classes(id)
);
🔑 外键与唯一索引
外键(FOREIGN KEY
)
作用: 确保子表字段在父表中存在对应值,维护表间参照完整性。
少用外键的五大原因
性能与运维成本
- 写入开销:外键检查导致锁竞争和性能下降(高并发场景敏感)。
- 表结构变更困难:需先删除外键才能修改父表结构,影响迭代效率。
应用层依赖
- ORM框架(如Hibernate)通过代码管理关联,替代数据库级约束。
- 微服务架构下,跨服务数据库无法使用外键,依赖RPC/消息队列保证一致性。
测试与迁移灵活性
- 自动化测试需按依赖顺序插入数据,复杂度增加。
- 数据迁移(ETL)时外键检查降低导入速度。
软删除与历史追踪冲突
- 软删除(
deleted_at
)需保留子表数据,与外键级联删除(ON DELETE CASCADE
)矛盾。
- 软删除(
团队经验与文化
- 敏捷开发优先快速迭代,数据库约束常被代码校验替代。
- 部分开发者对数据库设计不熟悉,依赖应用层逻辑。
那么,什么时候还要用外键?
适用场景
- 核心业务:如支付、库存系统,需严格一致性。
- 多表联合报表:避免“孤儿数据”。
- 大型单体应用:集中式数据库管理。
总结
- 优点:最简单、最透明的“数据层”完整性保证。
- 缺点:写性能/运维迭代成本高,ORM 和微服务下难以跨库使用。
- 实践:小项目、CRUD 频繁且不可容忍“孤儿数据”的核心业务表,依然推荐加外键;其余场景可权衡内部代码检查或使用分布式事务/幂等保证。
唯一索引(UNIQUE
)
作用: 确保字段值唯一(允许NULL
,且多个NULL
不冲突)。
唯一约束的两种实现方式
字段级定义
sqlCREATE TABLE students ( email VARCHAR(100) UNIQUE );
- 简洁,适合单字段唯一。
- 系统自动命名索引。
表级定义
sqlCREATE TABLE users ( UNIQUE KEY uni_phone (phone) );
- 支持多字段联合唯一(如
UNIQUE(user_id, role_id)
)。 - 可自定义索引名称,便于维护。
- 支持多字段联合唯一(如
联合唯一 vs 单字段唯一
类型 | 规则 | 示例场景 |
---|---|---|
联合唯一约束 | 组合值唯一,单字段可重复 | (country_code, phone) 唯一 |
单字段唯一约束 | 每个字段单独唯一 | username 唯一 |
索引对比
类型 | 适用场景 | 特点 |
---|---|---|
联合索引 | 组合查询(左前缀原则) | 查询(a, b) 快,单独查b 效率低 |
单字段索引 | 独立字段查询 | 单字段查询快,组合查询优化有限 |
实战建议
外键使用
- 核心业务表推荐使用,牺牲性能换取数据安全。
- 微服务或高并发场景优先依赖代码逻辑校验。
唯一约束
- 单字段唯一用字段级定义,联合唯一用表级定义。
- 生产环境建议表级写法,便于维护和扩展。
索引设计
- 高频联合查询字段使用联合索引(如
(user_id, order_id)
)。 - 独立查询字段单独建索引。
- 高频联合查询字段使用联合索引(如
总结
- 外键:强一致性场景的“双刃剑”,权衡性能与安全。
- 唯一索引:灵活保障数据唯一性,注意
NULL
处理与联合约束。 - 设计原则:根据业务需求选择约束类型,优先代码校验或数据库约束,避免过度设计。