首页/数据/数据库速查/约束与外键:主键 / 唯一 / 非空 / 外键
SQL 语法52 条

约束与外键:主键 / 唯一 / 非空 / 外键

用约束把数据正确性交给数据库:主键唯一标识、UNIQUE 防重复、NOT NULL 防缺失、外键保引用完整;外键在高并发写入场景要权衡。

数据库速查数据更新于 2026-10-13

把正确性交给数据库

约束是数据库层的数据守门人:主键唯一标识一行,唯一键防止重复,非空约束拒绝缺失值,CHECK 限制取值范围,外键保证引用完整性。优点是不依赖应用代码自律,缺点是外键检查会引入额外加锁与争用,在分库分表或高并发写入系统中常改为应用层保证。

基本信息

适用MySQL 5.7 / 8.0,InnoDB 支持外键与 CHECK(8.0.16+ 才真正生效)
常用约束PRIMARY KEY、UNIQUE、NOT NULL、DEFAULT、CHECK、FOREIGN KEY
开关FOREIGN_KEY_CHECKS 与 UNIQUE_CHECKS
注意唯一索引也是索引,会参与查询优化

外键与约束示例

外键与约束示例
CREATE TABLE order_items (
  id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,   # 主键唯一标识
  order_id BIGINT UNSIGNED NOT NULL,               # 非空约束
  sku VARCHAR(64) NOT NULL,
  qty INT NOT NULL CHECK (qty > 0),                # 取值约束(8.0.16+ 生效)
  CONSTRAINT fk_order FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE ON UPDATE RESTRICT
) ENGINE=InnoDB;
SET FOREIGN_KEY_CHECKS = 0;    # 批量导入期间可临时关闭
SET FOREIGN_KEY_CHECKS = 1;    # 导入完成必须恢复,避免脏数据长期存在

约束类型与影响

约束作用代价或注意
PRIMARY KEY唯一标识且不允许空聚簇索引基础,选择要稳定
UNIQUE防重复插入冲突报 1062,也会占用索引空间
NOT NULL / DEFAULT拒绝缺失值变更需评估存量数据
CHECK限制取值范围8.0.16 起才真正校验,旧版本会被忽略
FOREIGN KEY保证引用完整子表写入需检查父表并加锁,争用明显

典型使用场景

  • 交易类业务用唯一键防止重复下单
  • 订单与明细用外键保证引用关系,或改为应用层校验
  • 状态字段用 CHECK 限制取值范围
  • 批量导入前临时关闭外键检查以提速
  • 结构评审:确认关键约束是否缺失导致脏数据
批量导入期间可以临时关闭外键检查提速,但只应限于数据校验阶段,导入完成后必须立即恢复为开启状态。
ON DELETE CASCADE 会随父行删除静默级联删除子行,删除量可能远超预期,设计时要先想清影响范围并确认有备份。

约束变更的做法

  • 给存量表加唯一键前先查重复数据,否则 DDL 会直接失败
  • 加外键前确认父子表数据一致,避免校验不通过
  • 大表结构变更优先评估在线 DDL 或分批方案,先算清锁与资源占用

易错点

  • 外键带来的锁争用被低估:子表高频写入时会与父表检查互相阻塞
  • UNIQUE_CHECKS 或 FOREIGN_KEY_CHECKS 关闭后忘记恢复:脏数据长期存在且后续校验困难
  • 在 8.0.16 以下依赖 CHECK 约束:约束会被解析但被忽略,校验实际没生效
  • ON DELETE CASCADE 用于核心业务表:一次删除牵连大量行,风险高且难以限流

数据来源与参考

  • MySQL 8.0 Reference Manual: CREATE TABLE - Foreign Key Constraints

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌