数据库——外键的作用

article/2025/10/6 1:10:43

我们用一个比较实际的例子来描述问题,并讲解外键作用:

  • 当我们在网上购物的时候,我们有我们的帐号,还有我们所在不同地方的地址信息如公司,学校,家里,或者给亲戚朋友送个礼物,收货人信息也不一样。

我们就一步一步讨论以上提到的这些信息如何更合理的存储在数据库中

  • 第一步、我们把所用信息都存入到一个表中:
create table user_info(id char(36) primary key,user_name varchar(30) not null,password varchar(30) not null,real_name varchar(8),mobile char(11),address varchar(150)
);
insert into user_info (id,user_name,password,real_name,mobile,address) 
values ('51b28fe1-4ebf-41ac-a17b-d5e276861fd0','qiangzhogshou','123456','小明','12345678912','物理课');
insert into user_info (id,user_name,password,real_name,mobile,address) 
values ('cc95772b-75a2-4702-bd99-4c3b0322d606','qiangzhogshou','123456','李华','12345678934','英语课');
insert into user_info (id,user_name,password,real_name,mobile,address)
values ('c63028fd-cf8d-4dac-a278-b5cc8fd61e3c','qiangzhogshou','123456','文言文','12345678956','语文课');

在这里插入图片描述
我们发现如果在同一个表中,同一个账户的地址信息每增加一行都要多重复一行该账户的注册信息
问题:这种表结构存在严重的字段冗余(user_name和password列),如果个人信息字段比较多这一问题表现的越严重。

  • 第二步、把这些信息存入到两个表中(把账户信息,地址信息分开存储)
create table user_info(id char(36) primary key,user_name varchar(30) not null,password varchar(30) not null
)
insert into user_info (id,user_name,password) values ('51b28fe1-4ebf-41ac-a17b-d5e276861fd0','qiangzhogshou','123456');create table address(id char(36) primary key,user_info_id char(36),real_name varchar(8) not null,mobile char(11) not null,address varchar(150) not null
)
insert into address (id,user_info_id,real_name,mobile,address) 
values ('bfb9472a-7911-4e6f-a479-3b719454ebab','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','小明','12345678912','物理课');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('5227c6b9-45a2-44aa-8ac0-1f63a38d3b65','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','李华','12345678934','英语课');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('30b8584b-aa6a-4516-a623-03f487058586','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','文言文','12345678956','语文课');
  • 如下图为user_info表
    在这里插入图片描述
  • 如下图为address表
    在这里插入图片描述
    我们会发现,这样就基本解决了字段冗余的问题,帐户表中每个账户有不同的id,而address表中,用于对应账户信息的,只有一条账户id。

但是
①我们只是在address表里面写了一个新字段,内容是账户id,这只是在逻辑上把两个表联系起来,我们看到两个表的时候,比对了就知道
而数据库系统并没有建立起来两个表之间的联系,它只知道有两个表,不管内容一不一样,多么有逻辑,如果在建表的时候,没有建立两个表字段上逻辑关系的物理连接,数据库就只知道这是两个分开的表。
②这就导致,在对表执行操作的时候,无法捆绑另一个表信息的同步:比如删除了user_info中的数据,那么逻辑上应该地址也没有用了,但是因为是两个独立的表,address中的数据不会受影响。又或者在address中添加了一个随意的user_info_id的数据,但user_info中并不存在该用户;这两个例子中的“剩下的地址”和“不存在的用户”都是我们要继续解决的问题。

问题:这种表结构消除了字段冗余,但由于只是逻辑上的“外键”关系,所以依然无法保证数据完整性。

  • 第三步、在第二步的基础上建立两个表逻辑上的物理连接:外键

外键:一个表(表一)中的主键字段数据,可以索引到另一个表(表二)的对应字段数据,那么这个(表二中的)对应字段即为(表二的)外键。

作用:根据逻辑上的分析,通过外键:实现实际上的物理链接

应用到本例:

create table user_info(id char(36) primary key,user_name varchar(30) not null,password varchar(30) not null
)
insert into user_info (id,user_name,password) values ('51b28fe1-4ebf-41ac-a17b-d5e276861fd0','qiangzhogshou','123456');create table address(id char(36) primary key,user_info_id char(36),real_name varchar(8) not null,mobile char(11) not null,address varchar(150) not null,constraint address_user_info_id_fk foreign key(user_info_id) references user_info(id)
)
insert into address (id,user_info_id,real_name,mobile,address) 
values ('bfb9472a-7911-4e6f-a479-3b719454ebab','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','小明','12345678912','物理课');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('5227c6b9-45a2-44aa-8ac0-1f63a38d3b65','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','李华','12345678934','英语课');
insert into address (id,user_info_id,real_name,mobile,address) 
values ('30b8584b-aa6a-4516-a623-03f487058586','51b28fe1-4ebf-41ac-a17b-d5e276861fd0','文言文','12345678956','语文课');
  • 如下图为user_info表
    在这里插入图片描述
  • 如下图为address表
    在这里插入图片描述
    我们发现:
    ①使用外键前后,两个表看起来没有区别(这也可以说明:第二步中,只是逻辑通)
    ②外键的使用语句:
    constraint address_user_info_id_fk foreign key(user_info_id) references user_info(id)

结果:这种方案为user_info_id添加了外键,指向user_info表的主键,该约束起到了保护数据完整性的作用:如果删除的用户信息id已经在address表中使用,则该条数据无法删除;无法向address表中添加用户id不存在的地址信息。

总结:

外键的作用:
①解决了数据冗余问题
②实现两个表数据库内的的物理连接
③避免了脏数据的产生


http://chatgpt.dhexx.cn/article/7tGMadJn.shtml

相关文章

mysql数据库添加外键的四种方式

文章目录 一、添加外键的四种方式二、文档下载 一、添加外键的四种方式 1、 建表时直接使用FOREIGN KEY,这种方式外键名称自动生成。如下图。 FOREIGN KEY (user_id) REFERENCES t_user(id)2、 建表时使用CONSTRAINT指定外键名称。如下图。 CONSTRAINT fk_studen…

彻底理解数据库外键

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

什么是数据库外键?

外键 Teacher_id就是student的外键 Teacher是主表,student是子表(从表) 外键就是一个表中的一个字段引用了另一个表中的主键,引用的表叫做子表,被引用的表叫做主表,外键是一种约束,描述的是表之…

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

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

MySQL中的外键(foreign key)

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

显示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实现兼容低…