MySQL数据库中外键(foreign key)用法详解

 更新时间:2023年10月27日 08:49:32   作者:知其黑、受其白  
这篇文章主要给大家介绍了关于MySQL数据库中外键(foreign key)的相关资料,MySQL 外键约束可以用来保证表与表之间的关系完整性,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在MySQL中,我们都对主键比较了解,知道主键的主要作用是唯一区分表中的各个行;
但是,对于外键(foreign key) 比较陌生。

一、外键作用及其限制条件

1 外键的定义

外键是某个表中的一列,它包含在另一个表的主键中。

外键也是索引的一种,是通过一张表中的一列指向另一张表中的主键,来对两张表进行关联。

一张表可以有一个外键,也可以存在多个外键,与多张表进行关联。

2 外键的作用

外键的主要作用是保证数据的一致性和完整性,并且减少数据冗余。
主要体现在以下两个方面:

阻止执行

  • 从表插入新行,其外键值不是主表的主键值便阻止插入。
  • 从表修改外键值,新值不是主表的主键值便阻止修改。
  • 主表删除行,其主键值在从表里存在便阻止删除(要想删除,必须先删除从表的相关行)。
  • 主表修改主键值,旧值在从表里存在便阻止修改(要想修改,必须先删除从表的相关行)。

级联执行

  • 主表删除行,连带从表的相关行一起删除。
  • 主表修改主键值,连带从表相关行的外键值一起修改。

3 外键创建限制

父表必须已经存在于数据库中,或者是当前正在创建的表。

如果是后一种情况,则父表与子表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。

必须为父表定义主键。

外键中列的数目必须和父表的主键中列的数目相同。

两个表必须是 InnoDB 表,MyISAM 表暂时不支持外键。

外键列必须建立了索引,MySQL 4.1.2 以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显式建立。

外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如 int 和tinyint 可以,而 int 和 char 则不可以;

二、外键创建方法

可以在创建表时创建外键,也可以在已有的表中增加外键。

我们主要讲第二种方式创建外键。

1 创建外键的语法

ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY(外键字段名)
REFERENCES 外表表名(主键字段名)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]

其中,ON DELETE 和 ON UPDATE 表示事件触发限制,各参数意义如下:

参数意义
RESTRICT限制外表中的外键改动(默认值,也是最安全的设置)
CASCADE跟随外键改动
SET NULL设为null值
NO ACTION无动作
SET DEFAULT设为默认值

2 举例

(1)创建两张表

CREATE TABLE student
(
	id int (11) primary key auto_increment,
	name char(255),sex char(255),
	age int(11)
)charset utf8;
 
CREATE TABLE student_score
(
	id int (11) primary key auto_increment,
	class char(255),score char(255),
	student_id int(11)
)charset utf8;

(2)创建外键

ALTER TABLE student_score 
ADD CONSTRAINT s_id FOREIGN KEY (student_id) REFERENCES student (id);

(3)查看表结构

SHOW CREATE TABLE student;
SHOW CREATE TABLE student_score;
CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` char(255) DEFAULT NULL,
  `sex` char(255) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE `student_score` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `class` char(255) DEFAULT NULL,
  `score` char(255) DEFAULT NULL,
  `student_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `s_id` (`student_id`),
  CONSTRAINT `s_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

三、验证外键作用

1 先向主表中添加数据

再向从表中添加数据(从表中的外键已在主表中存在),正常运行。

#向 student 表中添加数据
INSERT INTO student (NAME, sex, age)
VALUES
	('小明', '男', '20');

#向 student_score 表中添加数据
INSERT INTO student_score (class, score, student_id)
VALUES
	('语文', '100', 1),
	('数学', '99', 1),
	('英语', '98', 1);

数据插入正常,无报错、警告信息。

在这里插入图片描述

2 触发限制使用默认值 RESTRICT 的情况下

(1)从表插入新行,外键值不在主表中,被阻止

INSERT INTO student_score (class, score, student_id)
VALUES
	('语文', '100', 2);
ERROR 1452 (23000) : Cannot ADD
OR UPDATE a child ROW : a FOREIGN KEY CONSTRAINT fails (
	`tts`.`student_score`,
	CONSTRAINT `s_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
)

(2)从表修改外键值,新值不是主表的主键值,阻止修改

UPDATE student_score
SET student_id = 2
WHERE
	student_id = 1;
ERROR 1452 (23000) : Cannot ADD
OR UPDATE a child ROW : a FOREIGN KEY CONSTRAINT fails (
	`tts`.`student_score`,
	CONSTRAINT `s_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
)

(3)主表删除行,其主键值在从表里存在便阻止删除(要想删除,必须先删除从表的相关行)

DELETE FROM student WHERE id = 1;
ERROR 1451 (23000) : Cannot DELETE
OR UPDATE a parent ROW : a FOREIGN KEY CONSTRAINT fails (
	`tts`.`student_score`,
	CONSTRAINT `s_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
)

(4)主表修改主键值,旧值在从表里存在便阻止修改(要想修改,必须先删除从表的相关行)

UPDATE student SET id = 2 WHERE id = 1;
ERROR 1451 (23000) : Cannot DELETE
OR UPDATE a parent ROW : a FOREIGN KEY CONSTRAINT fails (
	`tts`.`student_score`,
	CONSTRAINT `s_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`)
)

3 更改事件触发限制为 CASCADE

#删除旧的外键
ALTER TABLE student_score DROP FOREIGN KEY s_id;
 
#添加新的外键,修改事件触发限制为 CASCADE
ALTER TABLE student_score 
ADD CONSTRAINT s_id FOREIGN KEY (student_id) REFERENCES student (id) 
ON DELETE CASCADE ON UPDATE CASCADE;

(1)查看表结构

CREATE TABLE `student_score` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `class` char(255) DEFAULT NULL,
  `score` char(255) DEFAULT NULL,
  `student_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `s_id` (`student_id`),
  CONSTRAINT `s_id` FOREIGN KEY (`student_id`) REFERENCES `student` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

(2)查看此时两表中的数据

(3)此时,当主表修改主键值,从表中相关行的外键值将一起修改

UPDATE student SET id = 2 WHERE id = 1;

(4)如果主表删除行,从表中的相关行将一起被删除

DELETE FROM student WHERE id = 2;

4 结论

事件触发限制条件的不同,会造成两张表中的操作限制不同,其他几个限制条件相对好理解,大家可以自己进行尝试,体会其中的区别。

四、删除外键约束

ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
 
ALTER TABLE student_score DROP FOREIGN KEY s_id;

总结 

到此这篇关于MySQL数据库中外键(foreign key)的文章就介绍到这了,更多相关MySQL外键(foreign key)内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL 常用命令示例详解(使用mysql)

    MySQL 常用命令示例详解(使用mysql)

    本文系统介绍了MySQL常用命令,涵盖数据库管理、数据操作、备份恢复及查询优化,包括启停服务、连接操作、表结构管理、数据增删改查、文件导入导出和性能分析等实用脚本示例
    2025-07-07
  • MySQL 自定义函数CREATE FUNCTION示例

    MySQL 自定义函数CREATE FUNCTION示例

    本节主要介绍了MySQL 自定义函数CREATE FUNCTION,下面是示例代码,需要的朋友可以参考下
    2014-07-07
  • MySQL优化GROUP BY(松散索引扫描与紧凑索引扫描)

    MySQL优化GROUP BY(松散索引扫描与紧凑索引扫描)

    这篇文章主要介绍了MySQL优化GROUP BY(松散索引扫描与紧凑索引扫描),需要的朋友可以参考下
    2016-05-05
  • mysql的group by函数使用方法

    mysql的group by函数使用方法

    MySQL中的GROUP BY子句用于将查询结果按一个或多个列进行分组,通常与聚合函数,实现数据的分组统计,本文给大家介绍mysql的group by函数使用方法,感兴趣的朋友跟随小编一起看看吧
    2025-08-08
  • MySQL数据库备份与恢复全攻略

    MySQL数据库备份与恢复全攻略

    在现代应用中,数据库是核心组件之一,无论是个人项目还是企业级应用,数据的安全性和完整性都至关重要,为了防止数据丢失、损坏或意外删除,定期备份数据库是必不可少的,本文将详细介绍 MySQL 数据库的备份与恢复方法,需要的朋友可以参考下
    2024-10-10
  • 如何修改Linux服务器中的MySQL数据库密码

    如何修改Linux服务器中的MySQL数据库密码

    这篇文章主要介绍了如何修改Linux服务器中的MySQL数据库密码问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • MySQL数据库改名的详细方法教程

    MySQL数据库改名的详细方法教程

    在很多人看来Oracle数据库一旦建好后,数据库的名字就不能改变了,其实不然,下面这篇文章主要给大家介绍了关于MySQL数据库改名的相关资料,需要的朋友可以参考下
    2023-03-03
  • 关于mysql中innodb的count优化问题分享

    关于mysql中innodb的count优化问题分享

    关于mysql中innodb的count优化问题,有需要的朋友可以参考下
    2013-02-02
  • IDEA无法连接mysql数据库的6种解决方法大全

    IDEA无法连接mysql数据库的6种解决方法大全

    这篇文章主要介绍了IDEA无法连接mysql数据库的6种解决方法大全,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • MySQL使用innobackupex备份连接服务器失败的解决方法

    MySQL使用innobackupex备份连接服务器失败的解决方法

    这篇文章主要为大家详细介绍了MySQL使用innobackupex备份连接服务器失败的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02

最新评论