MySQL中的外键(foreign key)

本文深入讲解MySQL中外键的概念、作用及限制,包括外键的创建方法、事件触发限制及删除外键约束,通过实例演示外键如何确保数据一致性和完整性。
引言

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

一、外键、外键作用及其限制条件
1.外键的定义:
  1. 外键是某个表中的一列,它包含在另一个表的主键中。
  2. 外键也是索引的一种,是通过一张表中的一列指向另一张表中的主键,来对两张表进行关联。
  3. 一张表可以有一个外键,也可以存在多个外键,与多张表进行关联。
2.外键的作用:

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

阻止执行

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

级联执行

  1. 主表删除行,连带从表的相关行一起删除。
  2. 主表修改主键值,连带从表相关行的外键值一起修改。
3.外键创建限制
  1. 父表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则父表与子表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。
  2. 必须为父表定义主键。
  3. 外键中列的数目必须和父表的主键中列的数目相同。
  4. 两个表必须是InnoDB表,MyISAM表暂时不支持外键。
  5. 外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显式建立。
  6. 外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如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;


在这里插入图片描述

三、验证外键作用
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);

在这里插入图片描述

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

UPDATE student_score SET student_id = 2 WHERE student_id = 1;

在这里插入图片描述

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

DELETE FROM student WHERE id = 1;

在这里插入图片描述

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

UPDATE student SET id = 2 WHERE id = 1;

在这里插入图片描述

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)查看表结构

SHOW CREATE TABLE student_score;

在这里插入图片描述

(2)查看此时两表中的数据
在这里插入图片描述
在这里插入图片描述

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

UPDATE student SET id = 2 WHERE id = 1;

运行成功,查看两张表中的数据:
在这里插入图片描述
在这里插入图片描述

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

DELETE FROM student WHERE id = 2;

运行成功,查看两张表中的数据:
在这里插入图片描述
在这里插入图片描述

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

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

四、删除外键约束
1.语法
ALTER TABLE 表名 DROP FOREIGN KEY 外键名;
2.例子
ALTER TABLE student_score DROP FOREIGN KEY s_id;
<think>好的,我现在需要帮助用户解决在MySQL 8.0中添加关联的问题。首先,我应该回顾用户提供的引用内容,确保答案准确。用户提到了四个引用,涉及语法、错误处理、InnoDB引擎支持以及两种创建方式。 首先,约束需要满足几个条件:使用InnoDB引擎,字段类型和长度必须匹配,索引的存在等。用户可能遇到的常见问题比如Error 1215,应该解释如何避免。 接下来,我需要分步骤说明创建的方法。根据引用[3]和[4],有两种方式:建表时添加和后期修改。需要给出具体的SQL示例,比如CREATE TABLE和ALTER TABLE的语法,同时注意CONSTRAINT的可选性。 还要提到的更新和删除行为,比如CASCADE、SET NULL等,这在引用[4]中有涉及。此,注意事项部分应该涵盖引擎类型、字段匹配、索引和命名约束,这些在引用[1]、[2]和[4]中都有提到。 用户可能对错误1215的原因感兴趣,需要解释可能的原因,比如引擎不对或者字段不匹配。同时,提醒他们使用SHOW ENGINE INNODB STATUS来查看详细错误信息,这来自引用[1]。 最后,生成相关问题,覆盖的作用、错误处理、不同引擎支持、行为参数以及性能影响,这样用户可以有进一步的学习方向。 需要确保回答结构清晰,步骤明确,语法正确,并且引用正确标注。避免使用Markdown,用自然的中文分步骤解释,同时保持口语化。</think>在 MySQL 8.0 中创建约束需要遵循以下步骤: ### 一、创建的条件 1. 必须使用 `InnoDB` 存储引擎(可通过 `ENGINE=InnoDB` 指定)[^2] 2. 关联字段的数据类型和长度必须完全一致 3. 父表的被引用字段必须建立索引(主或唯一索引) ### 二、创建的两种方式 #### 方式1:建表时创建 ```sql CREATE TABLE 子表 ( 子表_id INT PRIMARY KEY, 父表_id INT, -- 定义语法: FOREIGN KEY (父表_id) REFERENCES 父表(父表主字段) ON DELETE CASCADE -- 级联删除 ON UPDATE RESTRICT -- 禁止更新 ) ENGINE=InnoDB; ``` #### 方式2:后期添加(推荐) ```sql ALTER TABLE 子表 ADD CONSTRAINT fk_自定义约束名 -- CONSTRAINT可选[^4] FOREIGN KEY (字段) REFERENCES 父表(字段) [ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}] [ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]; ``` ### 三、行为参数说明 | 参数 | 功能说明 | |------------|------------------------------| | CASCADE | 级联操作(删除/更新父表记录时同步子表)| | SET NULL | 将子表字段设为NULL | | RESTRICT | 默认值,禁止对父表进行相关操作| | NO ACTION | 与RESTRICT等效 | ### 四、注意事项 1. 出现 Error 1215 的常见原因: - 表未使用 InnoDB 引擎 - 字段类型/长度不匹配(如 INT 与 BIGINT) - 缺少父表对应字段的索引[^1] 2. 可通过 `SHOW ENGINE INNODB STATUS` 查看详细错误信息 3. 建议显式命名约束(`CONSTRAINT fk_name`)便于后续管理
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值