MySQL --- 多表设计

news2025/1/9 16:19:36

关于单表的操作(包括单表的设计、单表的增删改查操作)我们就已经学习完了。接下来我们就要来学习多表的操作,首先来学习多表的设计。

项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:

  • 一对多(多对一)
  • 多对多
  • 一对一

2.1 一对多

2.1.1 表设计

需求:根据页面原型及需求文档 ,完成部门员工的表结构设计

显然,部门和员工就是一种一对多的关系,因为一个部门下是会有多个员工的,但是一个员工只能归属于一个部门,其实这种关系,就是一对多的关系。在这种关系当中,由于一个部门对应多个员工,所以我们把部门叫一的一方,把员工叫多的一方。所以,在一对多的关系当中,我们把一的一方叫做父表,把多的一方叫子表,因为一个父亲可以有多个儿子。因为一个父亲可以有多个儿子,但是一个儿子只能有一个父亲。

提问:这种一对多的关系,在数据库表结构层面该怎么去体现呢?

回答:我们只需要在数据库表结构多的一方来增加一个外键 / 字段关联一的一方的主键即可。 

  • 员工管理页面原型:(前面已完成tb_emp表结构设计)

部门管理页面原型:

经过上述分析,现已明确的部门表结构:

  • 业务字段 : 部门名称
  • 基础字段 : id(主键)、创建时间、修改时间

部门表 - SQL语句: 

# 建议:创建新的数据库(多表设计存放在新数据库下)
create database db03;
use db03;

-- 部门表
create table tb_dept
(
    id int unsigned primary key auto_increment comment '主键ID',
    name varchar(10) not null unique  comment '部门名称',
    create_time datetime not null comment '创建时间',
    update_time datetime not null comment '修改时间'
) comment '部门表';

部门表创建好之后,我们还需要再修改下员工表。为什么要修改员工表呢?是因为我们之前设计员工表(单表)的时候,并没有考虑员工的归属部门。

员工表:添加归属部门字段

-- 员工表
create table tb_emp
(
    id          int unsigned auto_increment comment 'ID'
        primary key,
    username    varchar(20)                  not null comment '用户名',
    password    varchar(32) default '123456' null comment '密码',
    name        varchar(10)                  not null comment '姓名',
    gender      tinyint unsigned             not null comment '性别, 说明: 1 男, 2 女',
    image       varchar(300)                 null comment '图像',
    job         tinyint unsigned             null comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管',
    entrydate   date                         null comment '入职时间',

    dept_id int unsigned comment '归属的部门ID', -- 员工的归属部门,关联部门的id即可

    create_time datetime                     not null comment '创建时间',
    update_time datetime                     not null comment '修改时间',
    constraint username
        unique (username)
) comment '员工表';

员工表 - 部门表之间的关系:

一对多关系实现:在数据库表中多的一方,添加字段,来关联属于一这方的主键。

2.1.2 外键约束

问题

  • 表结构创建完毕后,我们看到两张表的数据分别为:

现在员工表中有五个员工都归属于1号部门(学工部),当删除了1号部门后,数据变为:

1号部门被删除了,但是依然还有5个员工是属于1号部门的。 此时:就出现数据的不完整、不一致了。

 问题分析

目前上述的两张表(员工表、部门表),在数据库层面,并未建立关联,所以是无法保证数据的一致性和完整性的。

问题解决

想解决上述的问题呢,我们就可以通过数据库中的"外键约束"来解决。

  • 外键约束:让两张表的数据建立连接,保证数据的一致性和完整性。  
  • 对应的关键字:foreign key

外键约束的语法:

外键约束的添加语法有两种,第一种就是在创建表结构的时候指定,第二种就是表结构创建完了我来添加一个外键。

如果是在创建表的时候添加外键,我们只需要在所有字段都罗列完成之后,后面加上这么一个约束,指定关键字constraint,指定外键约束的名称,然后指定外键的关键字foreign key,在小括号里面来指定哪个字段是外键,对于我们当前来说dept_id这个字段就是一个外键字段,然后再通过references来指定它所关联的主表的字段,这个主表指的就是我们刚才所介绍的父表,这是在创建表的时候指定。

如果表结构创建完了,我们可以通过alter table来指定表名,我们要修改哪一张表,add constraint然后指定外键名称,这就代表我们要添加一个约束,约束的名称是这个, 然后通过foreign key来只当这是一个外键约束,外键字段名是哪一个,再通过references来指定关联的主表的字段名。

-- 创建表时指定
create table 表名(
	字段名    数据类型,
	...
	[constraint]   [外键名称]  foreign  key (外键字段名)   references   主表 (主表列名)	
);


-- 建完表后,添加外键
alter table  表名  add constraint  外键名称  foreign key(外键字段名) references 主表(主表列名);

当然如果我们在项目开发阶段,如果我们要额外添加外键,就不需要再去记这些SQL语句了,直接图形化界面的方式就可以了。

方式2:图形化界面操作

指定当前表的哪个字段关联目标表的哪个字段 

当我们添加外键约束时,我们得保证当前数据库表中的数据是完整的。 所以,我们需要将之前删除掉的数据再添加回来。

当我们添加了外键之后,再删除ID为1的部门,就会发现,此时数据库报错了,不允许删除。

外键约束(foreign key):保证了数据的完整性和一致性。

外键约束添加成功之后,emp表的dept_id字段这里有一个蓝色的小钥匙,这个代表的就是外键约束。 

外键约束

当前,我们通过foreign key这种关键字所定义出来的这种外键我们叫物理外键。 

物理外键和逻辑外键

  • 物理外键

    • 概念:使用foreign key定义外键关联另外一张表。

    • 缺点:

      • 影响增、删、改的效率(需要检查外键关系)。

      • 仅用于单节点数据库,不适用与分布式、集群场景。

      • 容易引发数据库的死锁问题,消耗性能。

  • 逻辑外键

    • 概念:在业务层逻辑中,解决外键关联。

    • 通过逻辑外键,就可以很方便的解决上述问题。

在现在的企业开发中,很少会使用物理外键,都是使用逻辑外键。 甚至在一些数据库开发规范中,会明确指出禁止使用物理外键 foreign key

2.2 一对一

一对一关系比较典型的就是用户与身份证的关系,一个用户对应一张身份证,而一张身份证也只能归属于 / 关联一个用户。

一对一关系表在实际开发中应用起来比较简单,通常是用来做单表的拆分,也就是将一张大表拆分成两张小表,将大表中的一些基础字段放在一张表当中,将其他的字段放在另外一张表当中,以此来提高数据的操作效率。

一对一的应用场景: 用户表(基本信息+身份信息)

  • 基本信息:用户的ID、姓名、性别、手机号、学历

  • 身份信息:民族、生日、身份证号、身份证签发机关,身份证的有效期(开始时间、结束时间)

  • 如果在业务系统当中,对用户的基本信息查询频率特别的高,但是对于用户的身份信息查询频率很低,此时出于提高查询效率的考虑,我就可以将这张大表拆分成两张小表,第一张表存放的是用户的基本信息,而第二张表存放的就是用户的身份信息。他们两者之间一对一的关系,一个用户只能对应一个身份证,而一个身份证也只能关联一个用户。

那么在数据库层面怎么去体现上述两者之间是一对一的关系呢?

其实一对一我们可以看成一种特殊的一对多。一对多我们是怎么设计表关系的?是不是在多的一方添加外键。同样我们也可以通过外键来体现一对一之间的关系,我们只需要在任意一方来添加一个外键就可以了,这个外键来关联另一方的主键。

为了保证它们之间是绝对的一对一的关系,可以为该外键字段再加上一个unique唯一约束,此时就会保证这一列的值是不会重复的,这样也就保证了一个用户不能对应两个身份证。

 一对一 :在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

 SQL脚本:

2.3 多对多 

多对多的关系再开发中也是比较常见的,比如说像老师与学生的关系,一个学生可以有多个代课老师,一个代课老师也可以有多个学生。再比如,学生与课程的关系,一个学生可以选修多门课程,而一门课程也可以供多个学生选修。

案例:学生与课程的关系

  • 关系:一个学生可以选修多门课程,一门课程也可以供多个学生选择

思考:在数据库表结构当中,如何来体现这两张表之间的多对多的关系?

  • 实现关系:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

  • studentid用来关联的是学生表的主键,而courseid关联的是课程表的主键

  • 中间表当中的这些数据就维护了学生与课程之间的关系

-- 学生表
create table tb_student(
    id int auto_increment primary key comment '主键ID',
    name varchar(10) comment '姓名',
    no varchar(10) comment '学号'
) comment '学生表';
-- 学生表测试数据
insert into tb_student(name, no) values ('黛绮丝', '2000100101'),('谢逊', '2000100102'),('殷天正', '2000100103'),('韦一笑', '2000100104');

-- 课程表
create table tb_course(
   id int auto_increment primary key comment '主键ID',
   name varchar(10) comment '课程名称'
) comment '课程表';
-- 课程表测试数据
insert into tb_course (name) values ('Java'), ('PHP'), ('MySQL') , ('Hadoop');

-- 学生课程表(中间表)
create table tb_student_course(
   id int auto_increment comment '主键' primary key,
   student_id int not null comment '学生ID',
   course_id  int not null comment '课程ID',
   -- 分别用来关联学生表的主键和课程表的主键
   constraint fk_courseid foreign key (course_id) references tb_course (id),
   constraint fk_studentid foreign key (student_id) references tb_student (id)
)comment '学生课程中间表';
-- 学生课程表测试数据
insert into tb_student_course(student_id, course_id) values (1,1),(1,2),(1,3),(2,2),(2,3),(3,4);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/515242.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ChatGPT-4怎么对接-ChatGPT-4强化升级了哪些功能

ChatGPT-4怎么使用 使用ChatGPT-4,需要通过OpenAI的API接口来对接ChatGPT-4。OpenAI是一个人工智能公司,为开发者提供多个API接口,包括自然语言处理,图像处理等。ChatGPT-4是OpenAI开发的最新版本的聊天式对话模型,可…

React antd Form item「受控组件与非受控组件」子组件 defaultValue 不生效等问题总结

一、为什么 Form.Item 下的子组件 defaultValue 不生效? 当你为 Form.Item 设置 name 属性后,子组件会转为受控模式。因而 defaultValue 不会生效。你需要在 Form 上通过 initialValues 设置默认值。name 字段名,支持数组 类型:N…

2.存储器层次系统

存储器 随机访问存储器 RAM(随机存储器) SRAM 双稳态触发器,有电就保持不变,干扰消除后时会恢复到稳定值,晶体管多因此密集度低 DRAM 每个位存储为对一个电容的充电,对干扰敏感,漏电所以需要刷…

静态数码管

静态数码管 1、简介工作方式数码管静态显示原理 2、硬件设计3、软件设计4、 1、简介 一般共阳极数码管更为常用 好处:将驱动数码管的工作交到公共端(一般接驱动电源),加大驱动电源的功率自然要比加大IC芯片I/O口的驱动电流简单许…

【python 生成器】零基础也能轻松掌握的学习路线与参考资料

一、学习路线 了解生成器的概念和作用 首先,需要明确生成器的概念和作用,生成器是一种特殊的迭代器,它可以在循环中逐个地产生值,而不是一次性将所有的值产生出来。它的作用是使程序更加高效,达到节省内存等的效果。…

Linux 入门

文章目录 一、概述二、安装CentOS下载地址VMware下载地址 三、linux文件与目录结构Linux系统中一切皆文件Linux目录结构 四、VI/VIM 编辑器vi/vim是什么一般模式常用语法键盘图编辑模式指令模式 五、网络配置六、远程登陆七、系统管理Linux 中的进程和服务service 服务管理chkc…

几种常见的电源防反接电路

电源防反接,也即是防止电源的正负极搞反而导致电路损坏,例如你采用的是标准的DC口,那么没什么必要加入此种电路。而如果采用的是非常规的,如自定义的接插件等,那么就很有必要了。 举个例子:小编以前就采用…

企业在线制作帮助中心,选择:语雀、石墨、Baklib哪个好?

在当今互联网时代,越来越多的企业开始将帮助中心建设在线化。在线帮助中心的好处不仅可以提高用户的使用体验,也可以提高企业的工作效率。然而,选择一个合适的在线制作帮助中心工具却并不是一件容易的事情。在众多的在线制作帮助中心工具中&a…

Python3 入门教程||Python3 SMTP发送邮件||Python3 多线程

Python3 SMTP发送邮件 在Python3 中应用的SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。 python的 smtplib 提供了一种很方便的途径发送电子邮件。它对…

[cryptoverse CTF 2023] crypto部分

没打,完事作作题. Warmup 1 Decode the following ciphertext: GmvfHt8Kvq16282R6ej3o4A9Pp6MsN. Remember: CyberChef is your friend. Another great cipher decoding tool is Ciphey. 热身一下就凉,问了别人,用ciphey说是能自动解,但是安装报错 rot13base58 这个没有自动的…

JavaCollection集合:概述、体系特点、常用API、遍历方式

一、集合概述 集合和数组都是容器 数组 特点:数组定义完成并启动后,类型确定、长度固定。 劣势:在进行增删数据操作的时候,数组是不太合适的,增删数据都需要放弃原有数组或者移位。 使用场景:当业务数…

JMeter 常用的几种断言方法,你会了吗?

JMeter是一款常用的负载测试工具,通过模拟多线程并发请求来测试系统的负载能力和性能。在进行性能测试时,断言(Assertion)是非常重要的一部分,可以帮助我们验证测试结果的正确性。下面介绍JMeter常用的几种断言方法。 …

MySQL 运算符解析

1.算术运算符 算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行加 ()、减(-)、乘(*)、除(/)和取模(%&…

K8S:K8S部署常见错误及解决方法

目录 1、node节点kubelet服务起不来 2、安装cni网络插件时 kubectl get node master和node一直noready①有延时,需要等待10分钟左右,超过15分钟则有问题 3、部署报错kubectl get nodes No resources found 4、k8s部署报错error:kubectl ge…

OpenCV 直方图统计函数 cv::calcHist算是彻底弄明白了

参数说明 void calcHist( const Mat* images, int nimages,const int* channels, InputArray mask,OutputArray hist, int dims, const int* histSize,const float** ranges, bool uniform true, bool accumulate false );images 图像数组。每个图像的大小要一致&#xff0c…

龙的画法图片

由龙老师画素描中国龙的方法,大概可以遵循以下步骤: 确定龙的姿态和比例:在纸上简单地画出龙的基本形状和姿态,包括身体的长度,颈部、腿和尾巴的位置和比例关系。 添加细节:在基本形状的基础上,开始添加一些细节,如龙的头部、眼睛、鼻子、嘴巴、爪子等。注意要保持姿态和比例…

来,花半小时我带你入门vue

半小时入门vue 前言(!important)学习vue的前提什么是vue?vue的引入方式实例化一个对象和创建一个对象实例化一个vue对象模板语法1.插值表达式2.v-text和v-html指令3.v-bind指令4.v-on指令5.v-model指令6.v-if和v-show指令7.v-for指…

浅谈一下接口工具(jmeter、postman、swagger等)

一、接口都有哪些类型? 接口一般分为两种:1.程序内部的接口 2.系统对外的接口 系统对外的接口:比如你要从别的网站或服务器上获取资源或信息,别人肯定不会把 数据库共享给你,他只能给你提供一个他们写好的方法来获取…

MySQL中文乱码问题记录

概述 中文乱码是我们日常编程开发中经常会遇到的问题,包括: 浏览器(页面)显示乱码,参考记一次中文乱码排查解决流程Linux系统字体缺失导致中文乱码,参考Linux环境下Selenium截图乱码及字体安装及与字符集…

Excel突然弹出 请注意!您的文档的部分内容可能包含文档检测器无法删除的个人信息

环境: excel2016 Win10 专业版 问题描述: Excel突然弹出 请注意!您的文档的部分内容可能包含文档检测器无法删除的个人信息 解决方案: 1.打开excel点击左上角的“文件”菜单项 2.依次选择:选项-》信任中心-》信…