首 页
手机版

MYSQL数据库中外键(Foreign Key)用法介绍及实际案例讲解

发布时间:2026-10-01 19:52:44

1. 什么是MySQL外键?

  • 定义:外键(Foreign Key)是MySQL InnoDB引擎提供的参照完整性约束。外键字段引用另外一张表的主键或者唯一索引字段,用来保证关联数据合法。

  • 主表(父表):被引用的表,主键作为关联基准。

  • 从表(子表):包含外键字段的表,外键引用主表主键。

  • 约束效果:从表外键的值,只能是主表主键已存在的值,或者NULL。

2. 外键使用前提

  • 存储引擎必须是 InnoDB,MyISAM引擎不支持外键约束。

  • 外键字段和引用主表主键数据类型、字符集、排序规则必须完全一致。

  • 主表被引用字段必须建立主键索引或者唯一索引。

  • 外键字段建议单独建立索引,提升联表查询性能。

3. 四种级联操作说明

当父表记录删除或者更新时,通过ON DELETE、ON UPDATE控制子表外键行为:

约束行为说明
RESTRICT默认行为。如果子表存在关联数据,禁止删除/更新主表记录,直接抛出报错。
CASCADE级联操作,主表删除/更新,子表关联数据同步删除或更新。
SET NULL主表删除/更新,子表外键字段设置为NULL,前提是外键字段允许NULL。
NO ACTION和RESTRICT基本一致,不做任何操作,抛出约束报错。

4. 实战案例:用户表与订单表

业务场景:用户表 user 为主表,订单表 order 为子表。订单归属某个用户,通过user_id外键关联user表主键id。

创建主表 user(用户表)

CREATE TABLE `user` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户主键ID',
  `username` VARCHAR(50) NOT NULL COMMENT '用户名',
  `phone` VARCHAR(11) NOT NULL COMMENT '手机号',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户主表';

创建从表 order(订单表,定义外键)

CREATE TABLE `order` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '订单主键',
  `order_no` VARCHAR(32) NOT NULL COMMENT '订单编号',
  `user_id` INT UNSIGNED NOT NULL COMMENT '关联用户ID,外键',
  `amount` DECIMAL(10,2) NOT NULL COMMENT '订单金额',
  `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `fk_order_user` (`user_id`),
  CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`)
  REFERENCES `user` (`id`)
  ON DELETE RESTRICT
  ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单子表';

外键说明:

  • CONSTRAINT fk_order_user:外键名称,方便后续删除外键。

  • REFERENCES user(id):子表user_id引用主表user的id。

  • ON DELETE RESTRICT:用户存在订单时,不能删除用户。

  • ON UPDATE CASCADE:主表用户id更新,订单user_id同步更新。

插入测试数据

-- 主表插入用户
INSERT INTO `user`(username,phone) VALUES ('zhangsan','13800138000');
-- 子表插入订单(user_id=1在user表存在,可以成功)
INSERT INTO `order`(order_no,user_id,amount) VALUES ('ORD20260901001',1,99.00);
-- 插入user_id=999(用户不存在),外键直接报错,禁止插入
INSERT INTO `order`(order_no,user_id,amount) VALUES ('ORD20260901002',999,199.00);

删除主表数据(RESTRICT效果)

-- user表id=1存在订单,执行删除会报错,无法删除
DELETE FROM `user` WHERE id=1;

修改主表主键(CASCADE效果)

-- 更新主表id,子表user_id自动同步更新
UPDATE `user` SET id=10 WHERE id=1;
-- 查询订单表,user_id已经变成10
SELECT * FROM `order`;

5. 外键维护常用SQL

给已有表新增外键

ALTER TABLE `order`
ADD CONSTRAINT `fk_order_user`
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`)
ON DELETE RESTRICT ON UPDATE CASCADE;

删除外键

ALTER TABLE `order` DROP FOREIGN KEY `fk_order_user`;

查看表外键信息

-- 查看建表语句,可以看到外键定义
SHOW CREATE TABLE `order`;
-- 查询外键约束详情
SELECT * FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'user';

6. SET NULL 变体案例

业务场景:删除用户时,保留订单记录,订单user_id置空。注意:user_id字段必须允许NULL。

ALTER TABLE `order` MODIFY COLUMN `user_id` INT UNSIGNED NULL;
ALTER TABLE `order`
ADD CONSTRAINT `fk_order_user`
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`)
ON DELETE SET NULL
ON UPDATE CASCADE;

执行删除用户SQL后,订单表user_id自动变为NULL,订单数据保留。

7. 外键优缺点与开发建议

优点

  • 数据库层面强制数据参照完整性,杜绝无效关联脏数据。

  • 级联操作简化业务代码,不需要手写大量关联删除逻辑。

缺点

  • 增加写入、更新性能开销,每次修改都会校验约束。

  • 大表、高并发场景下容易产生锁等待,降低并发能力。

  • 分库分表架构无法使用数据库外键。

使用建议

  1. 中小型项目、内部管理系统,可以使用外键,减少脏数据。

  2. 高并发互联网核心业务、分库分表项目,推荐业务层代码维护数据一致性,不使用数据库外键。

  3. 开发测试环境可以开启外键校验,生产高并发场景谨慎使用。

8. 开发中常见坑

  • 字段类型不一致直接创建外键失败(INT 和 BIGINT 不能互相引用)。

  • 字符集、排序规则不一致,报外键创建失败。

  • 表中已有脏数据,会阻止外键创建,需要先清理脏数据。

  • 外键没有单独建索引,大表关联查询性能极差。

9. 总结

MySQL外键是InnoDB提供的参照完整性约束,核心作用是保证主从表之间引用合法。四种级联模式(RESTRICT/CASCADE/SET NULL/NO ACTION)适配不同业务场景。但高并发互联网项目一般不推荐在数据库层使用外键,优先在业务代码控制数据关联。


以上就是小编给玩家们带来的教程内容,更多教程请关注趣游软件园。