彻底理解数据库外键

article/2025/10/6 2:16:04

外键的定义

如果 公共关键字在一个关系中是 主关键字,那么这个 公共关键字被称为另一个关系的 外键。由此可见,外键表示了两个关系之间的相关联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。外键又称作外关键字。

举例:

student表:

class表:

由于一个班级可以有多个学生,在关系模型中,这两个表的关系可以称为“一对多”,即一个class的记录可以对应多个student表的记录。

为了表达这种一对多的关系,我们需要在student表中加入一列class_id,让它的值与class表的某条记录相对应。

这样,我们就可以根据class_id这个列直接定位出一个student表的记录应该对应到class的哪条记录。

在student表中,通过class_id的字段,可以把数据与另一张表关联起来,这种列称为外键。

外键并不是通过列名实现的,而是通过定义外键约束实现的:

//定义外键约束
ALTER TABLE student
ADD CONSTRAINT fk_class_id  //外键约束的名称fk_class_id可以任意
FOREIGN KEY (class_id)     //指定了class_id作为外键
REFERENCES class (id);    //指定了这个外键将关联到class表的id列(即class表的主键)
class_id为学生表的外键。(此时student表中的class_id与class表中的id表示的含义相同)
此时外键表是student表,主键表是class表。

要删除一个外键约束,也是通过ALTER TABLE实现的:

ALTER TABLE student
DROP FOREIGN KEY fk_class_id;
由于外键约束会降低数据库的性能,大部分互联网应用程序为了追求速度,并不设置外键约束,而是仅靠应用程序自身来保证逻辑的正确性。这种情况下,class_id仅仅是一个普通的列,只是它起到了外键的作用而已。

选取设置 MySQL 外键的字段

定义一个外键时,需要遵守下列规则:

  1. 父表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则父表与子表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。

  1. 必须为父表定义主键。

  1. 主键不能包含空值,但允许在外键中出现空值。也就是说,只要外键的每个非空值出现在指定的主键中,这个外键的内容就是正确的。

  1. 在父表的表名后面指定列名或列名的组合。这个列或列的组合必须是父表的主键或候选键。

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

  1. 外键中列的数据类型必须和父表主键中对应列的数据类型相同。

外键的作用

保持数据一致性,完整性。主要目的是控制存储在外键表中的数据。 使两张表形成关联,外键只能引用外表中的列的值或使用空值

外键约束

MySQL外键约束(FOREIGN KEY)用来在两个表的数据之间建立链接,它可以是一列或者多列。一个表可以有一个或多个外键。
外键是表的一个字段,不是本表的主键,但对应另一个表的主键。定义外键后,不允许删除另一个表中具有关联关系的行。

何为主表(父表)

对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表。

被引用的表叫主表(父表)。

何为从表(子表)

对于两个具有关联关系的表而言,相关联字段中外键所在的表就是从表。

定义了外键的表叫从表(子表)。

外键约束的作用:

阻止执行

从表插入新行,其外键值不是主表的主键值便阻止插入;

从表修改外键值,新值不是主表的主键值便阻止修改;

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

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

级联执行

主表删除行,连带从表的相关行一起删除;

主表修改主键值,连带从表相关行的外键值一起修改。两种方法提供给用户选择。无论选取哪种方法,从表里都不会有多余行。从另一个角度理解,用拒绝同一事物在从表中的标志与主表不一致来实现与主表中的标志一致。

两种实现方法,通过下面方式选择:

界面:设级联更新、级联删除两个选择方框,选取则级联执行、不选取则阻止执行;

命令:设CASCADE、RESTRICT两个可选项,CASCADE为级联执行、RESTRICT为阻止执行。

CASCADE:级联删除

在外键表的最后,加上on delete cascade 就是级联删除

再删除主表数据时和主表关联的子表数据也会删除

CREATE TABLE `student` (`id` bigint(64) NOT NULL AUTO_INCREMENT,`class_id` bigint(64) DEFAULT NULL,`name` varchar(32) COLLATE utf8_bin DEFAULT NULL,`age` int(32) DEFAULT NULL,`sex` varchar(32) COLLATE utf8_bin DEFAULT NULL,PRIMARY KEY (`id`),KEY `fk_class_id` (`class_id`),CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)  on delete cascade,
) 
所谓的级联删除,就是删除主键表的同时,外键表同时删除。
以上面的例子将就是,假如班级表中的某个班级被删除了,那么在学生表中要想查询这个被删除的班级号所对应的班级信息就会报错,因为已经不存在这个班级了,所以,删除班级表(主键表)时必须删除其他与之关联的表, 这里就说明了外键的作用,保持数据的一致性、完整性。当然反过来讲,你删除学生表中的记录,并不影响班级表中的数据,你查询班级号也能正确查询。 所以删除外键表中的数据并不影响主键表。

RESTRICT:约束/限制、NO ACTION(非活动,默认)

当取值为No Action或者Restrict时,则当在主键表中删除对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除。 (即外键表约束主键表)

SET NULL:级联置空

在在外键表的最后,加上on delete set null就是级联置空

再删除主表数据时,会把和主表关联的外键设置成NULL

CREATE TABLE `student` (`id` bigint(64) NOT NULL AUTO_INCREMENT,`class_id` bigint(64) DEFAULT NULL,`name` varchar(32) COLLATE utf8_bin DEFAULT NULL,`age` int(32) DEFAULT NULL,`sex` varchar(32) COLLATE utf8_bin DEFAULT NULL,PRIMARY KEY (`id`),KEY `fk_class_id` (`class_id`),CONSTRAINT `fk_class_id` FOREIGN KEY (`class_id`) REFERENCES `class` (`id`)  on  delete  set null,
) 
当取值为Set Null时,则当在主键表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键值为null,(一样是外键表约束主键表,不过这就要求该外键允许取null)。

NO ACTION和RESTRICT的区别:只有在及个别的情况下会导致区别,前者是在其他约束的动作之后执行,后者具有最高的优先权执行。

注意

删除表时,应该先删子表,后删父表,除非使用casecade constraints 解除关联。

先删除父表时会报错:有一个被foreign keys关联的 key的字段在子表中

<e>查询:drop table class
​
错误代码: 3730
Cannot drop table 'class' referenced by a foreign key constraint 'fk_class_id' on table 'student'

如果一定要先删除父表

使用casecade constraints解除关联就可以删掉父表


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

相关文章

什么是数据库外键?

外键 Teacher_id就是student的外键 Teacher是主表&#xff0c;student是子表&#xff08;从表&#xff09; 外键就是一个表中的一个字段引用了另一个表中的主键&#xff0c;引用的表叫做子表&#xff0c;被引用的表叫做主表&#xff0c;外键是一种约束&#xff0c;描述的是表之…

数据库常用命令之外键(foreign key)多对多(总结,基础)

我是小白&#xff0c;刚接触MySQL不久&#xff0c;现阶段正在学习&#xff0c;为此在这里留下自己的学习笔记。如果有错误的地方还请大家见谅&#xff0c;评论或者私发我错误的地方哦&#xff0c;谢谢大家&#xff0c;嘿嘿~ 外键&#xff08;foreign key&#xff09; 引言&…

MySQL中的外键(foreign key)

阅读目录 前言一、外键作用及其限制条件1 外键的定义2 外键的作用3 外键创建限制 二、外键创建方法1 创建外键的语法2 举例&#xff08;1&#xff09;创建两张表&#xff08;2&#xff09;创建外键&#xff08;3&#xff09;查看表结构 三、验证外键作用1 先向主表中添加数据2 …

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

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

老化测试Gsensor失败分析

在log中搜Gsensor可以看到如下&#xff1a; 在Y:\1\18045c1老化\bug127302c1_slog\last_log\2015-01-01-06-19-23\android\0-events-06-19-24.log中搜到如下&#xff1a; 行号 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 ----型号为&#xff1a;stk8baxx 1 查看原理图可以知道stk8baxx重力传感器 使用i2c1通道进行通讯&#xff0c;由于该重力传感器是不使用中断模式的进行触发的&#xff0c;所以不需要配置中断引脚。由此可以配置stk8baxx重力传感器的dts dts文件配置如…

APK无法识别gsensor问题剖析

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

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

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

Gsensor驱动概述

本文以Bma250驱动为例子&#xff0c;详细介绍Gsensor设计的一个模板。 gsensor驱动在系统中的层次如下图所示&#xff1a; 图中包含三个部分&#xff1a;hardware,driver, input&#xff1a; n Hardware&#xff1a;其实我们可以认为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 休眠震动唤醒功能怎么实现

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

G-sensor 介绍

转自&#xff1a;http://blog.chinaunix.net/uid-29595319-id-4200772.html G-sensor G-sensor是加速度传感器&#xff0c;可以通过其来获得分别来自三个不同轴向上的加速度用以通知上层应用做出相应处理。 由于地球的引力作用&#xff0c;gsensor平放时&#xff0c;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的程序包添加引用下面是客户端代码&#xff1a; 客户端代码&#xff1a; 运行效果&#xff1a; 遇到的问题&#xff1a; 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协议的安全通信问题。…