ON DELETE
和 ON UPDATE
的行为)。RESTRICT
、 CASCADE
、 SET NULL
、 NO ACTION
,接下来通过测试来演示各自的作用效果。-- 创建父表
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);
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类型的外键,如果该记录在子表中有引用,禁止删除或更新父表中的记录。
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 = 2
的user_id
的值被修改为3
总结:CASCADE
类型的外键,当父表中的记录被删除或更新时,子表中的相关记录也会自动被删除或更新。
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 = 1
的user_id
的值变为NULL
,order_id = 2
的user_id
的值变为NULL
,
总结:SET NULL
类型的外键,当父表记录被删除或更新时,子表中对应的外键值会更新为NULL
。
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的作用相同),如果该记录在子表中有引用,禁止删除或更新父表中的记录。
NULL
。NULL
。外键类型 | 适用场景 | 注意事项 |
---|---|---|
CASCADE | 父子关系强关联,父表删除或更新后子表无条件跟随。 | 谨慎使用,避免误删除或误更新。 |
SET NULL | 子表记录在父表删除或更新后仍有意义,允许外键列为 NULL。 | 子表的外键列必须允许 NULL,需谨防数据孤立。 |
NO ACTION / RESTRICT | 强制要求父表记录的删除或更新必须先解除子表关联。 | 增加了操作复杂性,但能严格保护数据完整性。 |
本文为冯奎原创文章,转载无需和我联系,但请注明来自冯奎博客fengkui.net
最新评论