首页/数据/SQL 速查/外键创建与级联选项
变更与事务52 条

外键创建与级联选项

用外键表达引用完整性:ON DELETE/UPDATE 决定父行变化时子行行为;外键列要建索引,写入路径也要评估锁影响。

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

外键的职责

外键把引用完整性交给数据库:子表外键列的值必须能在父表被引用列里找到,否则写入被拒绝。ON DELETE / ON UPDATE 决定父行被改动时子行怎么办——拒绝、跟着删、置空或置默认值。MySQL(InnoDB)与 PostgreSQL 都支持,但它会带来校验与加锁开销,进入写入路径。

基本信息

适用平台MySQL InnoDB 与 PostgreSQL 均已支持
语法FOREIGN KEY (子表列) REFERENCES 父表 (父表列)
级联选项RESTRICT / NO ACTION / CASCADE / SET NULL / SET DEFAULT
前提条件父表被引用列需唯一索引;两表列类型与字符集一致
延迟校验PostgreSQL 支持 DEFERRABLE 延迟到提交时校验

典型使用场景

  • 保证订单一定关联到存在的用户,杜绝孤儿记录
  • 父行删除时按业务决定连带删除明细或直接拒绝
  • 审计与日志类子表,防止写入不存在的业务主体
  • 数据迁移时延后到提交再校验,减少中间态报错(PostgreSQL)
  • 测试环境用级联删除快速清理关联数据

MySQL 建外键

MySQL 建外键
-- 先确认外键列有索引:InnoDB 缺索引时会自动建,显式建更可控
ALTER TABLE orders ADD INDEX idx_user_id (user_id);

ALTER TABLE orders
  ADD CONSTRAINT fk_orders_user
  FOREIGN KEY (user_id) REFERENCES users (id)
  ON DELETE CASCADE ON UPDATE RESTRICT;

SHOW CREATE TABLE orders;   -- 确认外键与索引都已生效

PostgreSQL 建外键

PostgreSQL 建外键
ALTER TABLE orders
  ADD CONSTRAINT fk_orders_user
  FOREIGN KEY (user_id) REFERENCES users (id)
  ON DELETE CASCADE ON UPDATE RESTRICT
  DEFERRABLE INITIALLY IMMEDIATE;   -- 需要时用 SET CONSTRAINTS DEFERRED 延迟校验

-- 查看外键定义
SELECT conname, confupdtype, confdeltype
FROM pg_constraint WHERE conrelid = 'orders'::regclass;

级联选项语义

选项父行被删除时父行主键被更新时
RESTRICT / NO ACTION有子行就拒绝删除有子行就拒绝更新
CASCADE连带删除所有子行子行外键列跟着改成新值
SET NULL子行外键置空(列必须可空)同样置空
SET DEFAULT子行外键置为默认值(需存在于父表)同样置为默认值
CASCADE 的破坏力:删掉一条父行会连带清空全部相关子行。生产上启用前要确认业务语义,并先统计子表数据量,避免一条 DELETE 引发连锁删除。
外键不能跨实例,分库分表后数据库层面无法再保证一致性,只能靠应用层校验与对账补偿。另外高并发写入时外键检查会持有共享锁,可能放大锁竞争,大表上线前先压测。

易错点

  • 生产大表随手加外键:存量脏数据会让加约束直接失败,需先清理孤儿行;校验与锁开销还会进入写入路径,先评估必要性
  • CASCADE 用顺手:父行删除连带清空子表,误删无法回滚,启用前确认业务语义
  • 两表列类型或字符集不一致:外键创建失败或校验走不动索引,建表时就对齐类型与排序规则
  • ON DELETE SET NULL 配在 NOT NULL 的外键列上:删除父行时报错或语义自相矛盾,置空要求列可空
  • 在分库分表或跨实例场景依赖外键:约束根本建不起来,需改用应用层校验与对账补偿

数据来源与参考

  • MySQL 8.0 Reference Manual · FOREIGN KEY Constraints
  • PostgreSQL Documentation · Foreign Keys
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌