当前位置: 代码网 > it编程>数据库>Mysql > MySQL外键类型及应用场景总结

MySQL外键类型及应用场景总结

2025年02月13日 Mysql 我要评论
前言: mysql的外键简介:在 mysql 中,外键 (foreign key) 用于建立和强制表之间的关联,确保数据的一致性和完整性。外键的作用主要是限制和维护引用完整性 (referential

前言mysql的外键简介:在 mysql 中,外键 (foreign key) 用于建立和强制表之间的关联,确保数据的一致性和完整性。外键的作用主要是限制和维护引用完整性 (referential integrity)。

  • 主要体现在引用操作发生变化时的处理方式(即 on deleteon update 的行为)。
  • 外键类型一共有四种restrictcascadeset nullno action。接下来通过测试来演示各自的作用效果。

1、外键效果演示

1.1、创建和添加两张表数据

-- 创建父表
create table `users` (
  `user_id` int not null auto_increment,
  `username` varchar(255) not null,
  primary key (`user_id`)
);

-- 创建子表
create table `orders` (
  `order_id` int not null auto_increment,
  `order_date` date not null,
  `user_id` int,
  primary key (`order_id`)
);

-- 插入父表数据
insert into `users` (`username`) values ('alice');
insert into `users` (`username`) values ('bob');

-- 插入子表数据
insert into `orders` (`order_date`, `user_id`) values ('2024-12-25', 1);
insert into `orders` (`order_date`, `user_id`) values ('2024-12-26', 2);

1.2、测试外键作用效果

1.2.1、restrict

  • 创建restrict外键
-- 添加外键约束到现有的子表 `orders`
alter table `orders`
add constraint `fk_user_id`
foreign key (`user_id`)
references `users`(`user_id`)
on delete restrict
on update restrict;
  • 主表 删除和更新 已在 子表的外键中已存在 的数据
-- 删除已被引用的外键
delete from `users` where `user_id` = 1

-- 输出结果 --
> 1451 - cannot delete or update a parent row: a foreign key constraint fails (`test`.`orders`, constraint `fk_user_id` foreign key (`user_id`) references `users` (`user_id`) on delete restrict on update restrict)
> 查询时间: 0.013s


-- 修改已被引用的外键
update `users` set `user_id` = 3 where `user_id` = 1

-- 输出结果 --
> 1451 - cannot delete or update a parent row: a foreign key constraint fails (`test`.`orders`, constraint `fk_user_id` foreign key (`user_id`) references `users` (`user_id`) on delete restrict on update restrict)
> 查询时间: 0.009s
  • 查看子表变化

因为删除和更新都执行失败,所以子表没有变化。

总结restrict类型的外键,如果该记录在子表中有引用,禁止删除或更新父表中的记录。

1.2.2、cascade

  • 创建cascade外键
-- 添加外键约束到 `orders` 表,使用 cascade
alter table `orders`
add constraint `fk_user_id`
foreign key (`user_id`)
references `users`(`user_id`)
on delete cascade
on update cascade;
  • 主表 删除和更新 已在 子表的外键中已存在 的数据
-- 删除已被引用的外键
delete from `users` where `user_id` = 1

-- 输出结果 --
> affected rows: 1
> 查询时间: 0.016s


-- 修改已被引用的外键
update `users` set `user_id` = 3 where `user_id` = 2

-- 输出结果 --
> affected rows: 1
> 查询时间: 0.013s
  • 查看子表变化

因为两条sql都执行成功。order_id = 1的数据被删除,order_id = 2user_id的值被修改为3

总结cascade类型的外键,当父表中的记录被删除或更新时,子表中的相关记录也会自动被删除或更新。

1.2.3、set null

  • 创建set null外键
-- 确保子表的外键列允许 null
alter table `orders`
modify column `user_id` int null;

-- 添加外键约束到 `orders` 表,使用 set null
alter table `orders`
add constraint `fk_user_id`
foreign key (`user_id`)
references `users`(`user_id`)
on delete set null
on update set null;
  • 主表 删除和更新 已在 子表的外键中已存在 的数据
-- 删除已被引用的外键
delete from `users` where `user_id` = 1

-- 输出结果 --
> affected rows: 1
> 查询时间: 0.014s


-- 修改已被引用的外键
update `users` set `user_id` = 3 where `user_id` = 2

-- 输出结果 --
> affected rows: 1
> 查询时间: 0.012s
  • 查看子表变化

两条sql都执行成功。order_id = 1user_id的值变为nullorder_id = 2user_id的值变为null

总结set null类型的外键,当父表记录被删除或更新时,子表中对应的外键值会更新为 null

1.2.4、no action

  • 创建no action外键
-- 添加外键约束,使用 no action
alter table `orders`
add constraint `fk_user_id`
foreign key (`user_id`)
references `users`(`user_id`)
on delete no action
on update no action;
  • 主表 删除和更新 已在 子表的外键中已存在 的数据
-- 删除已被引用的外键
delete from `users` where `user_id` = 1

-- 输出结果 --
> 1451 - cannot delete or update a parent row: a foreign key constraint fails (`test`.`orders`, constraint `fk_user_id` foreign key (`user_id`) references `users` (`user_id`))
> 查询时间: 0.013s


-- 修改已被引甮的外键
update `users` set `user_id` = 3 where `user_id` = 2

-- 输出结果 --
> 1451 - cannot delete or update a parent row: a foreign key constraint fails (`test`.`orders`, constraint `fk_user_id` foreign key (`user_id`) references `users` (`user_id`))
> 查询时间: 0.025s
  • 查看子表变化

因为删除和更新都执行失败,所以子表没有变化。

总结no action类型的外键(和restrict的作用相同),如果该记录在子表中有引用,禁止删除或更新父表中的记录。

1.3、外键作用描述以及优缺点总结

1.3.1、restrict

  • 描述:即父表记录在被子表引用时,无法被删除或更新。
  • 适用场景:适合需要严格控制父表记录操作的场景。
  • 优点:防止意外的数据丢失。
  • 缺点:增加操作复杂性。

1.3.2、cascade

  • 描述:级联操作。当父表中的记录被删除或更新时,子表中的相关记录也会自动被删除或更新。
  • 适用场景:当子表记录与父表记录绑定紧密时,例如订单表和订单明细表。
  • 优点:简化了复杂的删除或更新操作,自动维护数据一致性。
  • 缺点:操作不当可能导致数据大量丢失或被误修改。

1.3.3、set null

  • 描述:当父表记录被删除或更新时,子表中对应的外键值会设置为 null
  • 适用场景:当子表的记录在父表记录删除后依然有意义时,外键列必须允许 null
  • 优点:保留了子表记录,同时删除或更新父表记录。
  • 缺点:如果没有后续维护,可能导致孤立的数据。

1.3.4、no action(等价于 restrict)

  • 描述:禁止删除或更新父表中的记录,如果该记录在子表中有引用。
  • 适用场景:强制父表记录必须首先解除子表中的关联。
  • 优点:明确控制了数据的删除或更新,防止意外影响子表数据。
  • 缺点:操作复杂性增加,要求开发者手动处理关联关系。

2、外键类型适用场景总结(表格)

外键类型适用场景注意事项
cascade父子关系强关联,父表删除或更新后子表无条件跟随。谨慎使用,避免误删除或误更新。
set null子表记录在父表删除或更新后仍有意义,允许外键列为 null。子表的外键列必须允许 null,需谨防数据孤立。
no action / restrict强制要求父表记录的删除或更新必须先解除子表关联。增加了操作复杂性,但能严格保护数据完整性。

3、外键于业务开发而言的优缺点

3.1、优点

  • 数据完整性: 防止孤立记录,确保父表与子表之间的关联关系一致。
  • 自动化处理: 配合 cascade 或 set null,可以自动处理相关记录,减少手动操作的复杂性。
  • 业务约束: 通过外键约束明确表间关系,增强业务逻辑的约束力。

3.2、缺点

  • 性能开销: 外键约束会对插入、更新、删除操作产生额外的性能开销,尤其是在大量操作时。
  • 操作复杂性: 需要对数据表操作进行规划,增加开发维护成本。
  • 限制灵活性: 外键约束的存在可能限制某些业务操作,例如无法随意删除父表记录。

4、外键的使用注意事项

  • 引擎限制: mysql 的外键功能仅支持 innodb 存储引擎。
  • 索引要求: 外键列和被引用列都必须建立索引(通常是主键或唯一键)。
  • 规划数据关系: 在设计时需明确父表与子表之间的关系和操作逻辑,避免误操作。
  • 性能考虑: 在高并发或大规模数据操作时,外键可能影响性能,需谨慎权衡。

以上就是mysql外键类型及应用场景总结的详细内容,更多关于mysql外键类型及应用的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com