MySQL中的外键(foreign key)

article/2025/10/6 3:01:39

阅读目录

  • 前言
    • 一、外键作用及其限制条件
      • 1 外键的定义
      • 2 外键的作用
      • 3 外键创建限制
    • 二、外键创建方法
      • 1 创建外键的语法
      • 2 举例
        • (1)创建两张表
        • (2)创建外键
        • (3)查看表结构
    • 三、验证外键作用
      • 1 先向主表中添加数据
      • 2 触发限制使用默认值 RESTRICT 的情况下
        • (1)从表插入新行,外键值不在主表中,被阻止
        • (2)从表修改外键值,新值不是主表的主键值,阻止修改
        • (3)主表删除行,其主键值在从表里存在便阻止删除(要想删除,必须先删除从表的相关行)
        • (4)主表修改主键值,旧值在从表里存在便阻止修改(要想修改,必须先删除从表的相关行)
      • 3 更改事件触发限制为 CASCADE
        • (1)查看表结构
        • (2)查看此时两表中的数据
        • (3)此时,当主表修改主键值,从表中相关行的外键值将一起修改
        • (4)如果主表删除行,从表中的相关行将一起被删除
      • 4 结论
    • 四、删除外键约束

前言

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

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

1 外键的定义

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

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

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

2 外键的作用

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

阻止执行

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

级联执行

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

3 外键创建限制

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

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

必须为父表定义主键。

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

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

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

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

二、外键创建方法

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

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

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 DELETEON 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
WHEREstudent_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;

http://chatgpt.dhexx.cn/article/pj2wWw8b.shtml

相关文章

显示gsensor即时数据的apk 用gsensor来判断手机的静和动

即时显示gsensor的数据,可以在调试重力感应器驱动和测试手机性能时起到很好的作用。类似的,SensorEventListener还可以用在其他感应器的场合,比如光感应、地磁感应。这里用两种方式来完成读取并显示gsensor数据的功能,一种是activ…

老化测试Gsensor失败分析

在log中搜Gsensor可以看到如下: 在Y:\1\18045c1老化\bug127302c1_slog\last_log\2015-01-01-06-19-23\android\0-events-06-19-24.log中搜到如下: 行号 500 - 01-01 06:36:08.996 664 2050 I am_create_activity: [0,509924699,15,com.wingtech.runin…

MTK 9.0平台调试gsensor

MTK 9.0平台调试gsensor ----型号为:stk8baxx 1 查看原理图可以知道stk8baxx重力传感器 使用i2c1通道进行通讯,由于该重力传感器是不使用中断模式的进行触发的,所以不需要配置中断引脚。由此可以配置stk8baxx重力传感器的dts dts文件配置如…

APK无法识别gsensor问题剖析

APK无法识别gsensor问题的原因有很多,这里只是提供一条思路,解决现有项目遇到的问题。 1、确保驱动层可以工作。 2、打印LOGCAT数据,分析sensorservice流程 1、移植流程: 步骤:移植gsensor驱动,mc3413&am…

mtk平台gsensor,msensor方向确定方法

在gsensor和msensor驱动调试中,一个很重要的参数就是direction。 direction与芯片、layout和结构三者结合,才能最终确定该参数值。 mtk平台中该参数的示意图 在mtk10.0的kernel中提供了一个简单的调试接口,用于确认该参数值。 内核节点 /…

Gsensor驱动概述

本文以Bma250驱动为例子,详细介绍Gsensor设计的一个模板。 gsensor驱动在系统中的层次如下图所示: 图中包含三个部分:hardware,driver, input: n Hardware:其实我们可以认为Gsensor也是一个I2C设备。整个Gsens…

MTK平台Android Gsensor数据校准与数据获取

http://blog.csdn.net/morixinguan/article/details/76850600 上节,写WIFI MAC地址的时候我们已经知道,MTKAndroid系统的Gsensor校准的数据其实也是存储在NVRAM中的,Gsensor隶属于传感器系统架构。 接下来我们来看下Gsensor校准的基准图像: 那么如何来校准Gsensor的X,Y,Z三…

android g sensor,android gsensor 休眠震动唤醒功能怎么实现

一、唤醒源 设备休眠后,通过触发唤醒源使设备恢复正常工作模式。设备唤醒源有多种,对于Android设备常见的就有PowerKey、来电唤醒、Alarm唤醒等。 唤醒源的实现处于内核空间,本文重点讨论下PowerKey作为唤醒源的具体实现。 二、PowerKey唤醒源…

G-sensor 介绍

转自:http://blog.chinaunix.net/uid-29595319-id-4200772.html G-sensor G-sensor是加速度传感器,可以通过其来获得分别来自三个不同轴向上的加速度用以通知上层应用做出相应处理。 由于地球的引力作用,gsensor平放时,Z轴方向能…

G-sensor概述及常用概念整理【转】

本文转载自:http://www.jianshu.com/p/d471958189a0?nomobile=yesG 本文对G-sensor进行整理,先介绍G-sensor的一些基本概念,再具体讲解BOSCH、ST、ADI三家的G-sensor,其中BOSCH的G-sensor重点讲BMA222E,ST的G-sensor重点讲LIS2DH12,ADI的G-sensor具体讲ADXL362。 一、G-…

初次使用Fleck+redis订阅发布实现学习小demo

https://www.cnblogs.com/SupPilot/p/10396333.html 首先安装Fleck的程序包添加引用下面是客户端代码: 客户端代码: 运行效果: 遇到的问题: Q:通常每个套接字地址(协议/网络地址/端口)只允许使用一次 A:是因为本萌新把WebSocke…

core+Fleck+redis

1.新建core版控制台程序引用 2.初始化websocket class Program { //客户端url以及其对应的Socket对象字典 static IDictionary<string, IWebSocketConnection> dic_Sockets new Dictionary<string, IWebSocketConnection>(); static …

[c#]使用Fleck实现简单的WebSocket含兼容低版本IE

WebSocket是html5的一种协议,那么就表示要使用websocket客户端的浏览器就要支持html5。 对于不支持的使用flash去解决。 Fleck源码地址 服务端采用的是Fleck,Fleck的好处就是简单方便,作者已经进行了完整的封装,可以根据自己情况进行修改 兼容低版本IE 使用flash实现兼容低…

C#实现WebSocket(基于Fleck-服务端和WebSocketSharp-客户端)

C#实现WebSocket(基于Fleck-服务端和WebSocketSharp-客户端) 官网&#xff1a;https://github.com/sta/websocket-sharp 客户端 private void btn_Connect_Click_1(object sender, EventArgs e){Console.WriteLine("Websocket Demo");WebSocket web new WebSocket(…

C#通过fleck实现wss协议的WebSocket多人Web实时聊天(附源码)

前言 最近想做一个Web版的即时聊天为后面开发的各项功能做辅助&#xff0c;就需要浏览器与服务器能够实时通讯。而WebSocket这种双向通信协议&#xff0c;就很合适用来实现这种需求。 本篇文章主要解决C#如何实现WebSocket服务端和Javascript客户端基于wss协议的安全通信问题。…

Asp.Net Mvc基于Fleck开发的多人网页版即时聊天室

一、项目的核心说明 1、Fleck这个是实现websocket一个比较简单第三方组件&#xff0c;它不需要安装额外的容器。本身也就几个接口可供调用。 2、项目是基于.net framework 4.7.2 &#xff0c;在vs2019上开发的&#xff0c;没试过在低版本上运行。但是代码上没怎么用到新特性&…

winfrom+Fleck 上传文件

最近这个项目要做一个Winfrom上传Execl到服务器。 就想到之前用Fleck做的一个小功能&#xff0c;但是客户端Web端的。百度吧&#xff0c;看有没有办法&#xff0c;开始找到fw4 &#xff0c;但是要引用它的dll&#xff0c;是可以&#xff0c;继续找了会结果找到ClientWebSocket…

C#工作总结(一):Fleck的WebSocket使用

一.引子&#xff08;Foreword&#xff09; 最近公司里面要做窗体和网页交互的功能。网上找了一下资料&#xff0c;这里做一个简单的扩充和整理&#xff0c;部分内容可能是摘自其他博客&#xff0c;这里会注明出处和原文地址供大家和自己日后查阅。 二.基础知识&#xff08;Foun…