MySQL —— 表的设计

news2024/9/25 11:16:14

表的设计

在设计表之前,我们需要从需求中获得实体(实体就是一张张表),实体的属性就是表中的字段(列),然后确定实体与实体之间的关系,最后使用 SQL 语句去创建具体的表

在设计表的时候我们会遵守一些规则,这些规则叫做三大范式(范式是描述数据关系的模型),下面我们来了解一下三大范式。

第一范式

第一范式是关系型数据库的一个基本要求,如果不满足第一范式就不是关系型数据库。

第一范式要求表里的字段不能继续拆分

举个例子:
我们定义一个学生表,但是你只是给了一个字段——学生,可是这个学生范围很广泛,有学生的姓名,性别,年龄,班级,学号等等,说明学生这个字段是可以拆分的,所以你最开始定义的表是不符合第一范式的。

如果一张表里的所有的字段都无法拆分那就满足第一方式,还是学生表为例子:现在创建了学号,姓名,性别,年龄这四个字段组成学生表那就符合第一范式,因为每一个字段都是不可分的。

在定义表的时候,对照数据中的数据类型,将每一个字段都可以用一个数据类型表示,那么当前这个表就天然满足第一范式

第二范式

第二范式在满足第一范式的基础上,存在于复合主键的情况下,不存在非关键字段对任意候选键的部分函数依赖

简单来说,对于由两个或者多个关键字段(即复合主键)决定一条记录的情况的时候,如果一行数据中非主键的字段与复合主键的部分字段存在关系,就说明存在部分函数依赖,不满足第二范式

现在举个例子:
假设我有一张学生成绩表,表里有一下这些字段:
在这里插入图片描述

这张表设计是存在问题的,首先我们可以假设将学号设置为主键,然后通过学号我们是可以确定这个学生的姓名性别年龄以及班级的,但是再往后看,我们会发现通过课程名称我们应该是可以找到课程的学分,这时候这个课程的成绩到底是由什么决定的,那应该就是学生和课程共同决定的(学生参加这个课程的考试之后就会有成绩),那这时候我们就可以将学号和课程名称定义为复合主键,在这张表中姓名和课程学分就是非关键字段,但是却与候选键发生了函数依赖(也就是存在关系),那么就会违反第二范式。

以上面的学生成绩表为例:
将表进行拆分,学生表(学生学号,姓名,性别,年龄与班级),课程表(课程编号、名称,课程学分),还有一张课程成绩表(学号,课程编号,成绩)。

如果一张表没有复合主键,那么这张表一定满足第二范式。

如果不满足第二范式有什么后果?

  1. 造成数据冗余:就像上面的表,本来我需要查看的是学生考了多少分,但是你还告诉我学生的性别,年龄,班级甚至课程学分我都不想知道,这就是数据冗余,并且很浪费空间,应该让每一张表都有自己特定的数据进行保存,而不是全部塞进去
  2. 更新可能会出现异常:假设你要修改课程对应的学分,那你是不是要把每一个都有这个课程的数据行都要进行修改,不仅费时费力,万一数据库服务器突然坏了一秒钟,你之前更新的数据还不一定会保存下来。
  3. 插入异常,如果你要新增一门新课程,那你怎么往这张表插入数据,设计表的时候有些列不能为空的,那你是不是还要伪造哪些空数据,或者你等到有人考了这门成绩出来以后再加入数据库中(黄瓜菜都凉了)。
  4. 删除异常:假设所有参加 JavaEE 课程的同学都毕业了,但是JavaEE 的新学生还没这么快考试,那你如果删除这些毕业的人的数据的时候,也就连JavaEE 的课程信息也删除了。

如何避免第二范式:
在设计复合主键的时候,一定要考虑清楚其他字段会不会与复合存在部分函数联系。

第三范式

第三范式在第二范式的基础上,不存在非关键字段对任一候选键存在传递依赖。

以下面的学生表为例:
在这里插入图片描述

这张表主键定义为学号,但是我们可以 从学号得知学院名称 再得知学院的地址和电话,由于学院名称是非关键字段,所以存在了传递关系。

那该如何设计这张学生表?
设计成两张表,一个学院表(学院编号,学院名称,学院电话,学院地址)
一张学生表(学号,姓名,学院编号)设计成主外键键关系即可。

表的关系

一对一

举个例子:一个中国公民只有一个身份证

如何设计表:
创建两张表,分别记录中国公民的个人信息(姓名,电话,现居地址),身份证信息(身份证号,姓名,年龄,性别)
然后我们可以再公民表中设计一个外键(身份证号)。

create table idcard(
	id bigint primary key comment '身份证号',
	name varchar(20) not null comment '姓名',
	gender varchar(1) not null comment '性别',
	age int not null comment '年龄'
);

create table person(
	id bigint primary key auto_increment comment '编号',
	name varchar(20) not null comment '姓名',
	address varchar(100) comment '现居地址',
	foreign key (id) references idcard(id)
);

一对多(多对一)

举例:一个班级存在很多个学生,这是一对多的关系
同理,很多个学生都在一个班级,这是多对一的关系

如何设计表:
还是一样,先创建不同的实体表,再去建立联系

演示:创建班级表(班级编号,班级人数)
再创建学生表(学生学号,姓名,年龄,所属班级)
最后确定关系,我们可以在学生表添加一个班级外键:

create table class(
	id bigint primary key comment '班级编号',
	num int comment '人数'
);

create table student (
	id bigint primary key auto_increment comment '学生学号',
	name varchar(50) not null comment '姓名',
	age int comment '年龄',
	foreign key (id) references class(id)
);

多对多

举个例子:学生与课程的关系,一个学生可以选择很多个课程,一个课程同时也可以包含很多个学生。

如何设计?
首先分别创建好实体表,一张学生表(学生学号,姓名,年龄) 一张课程表(课程编号,课程名称,课程学分)
然后确定关系发现是多对多,那就再创建一张表——关系表(关系表自身的编号,学生学号,课程编号)

create table student (
	id bigint primary key auto_increment comment '学生学号',
	name varchar(50) not null comment '姓名',
	age int comment '年龄'
);

create table course(
	id bigint primary key auto_increment comment '课程编号',
	name varchar(20) not null comment '课程名称',
	score decimal(2,1) comment '学分'
);

create table student_course (
	id bigint primary key comment '自身编号',
	student_id bigint not null comment '学生学号',
	course_id bigint not null comment '课程编号',
	foreign key (student_id) references student(id),
	foreign key (course_id) references course(id)
);

我们还可以在这张关系表中添加一个成绩的字段。

没有关系

对于没有关系的表,我们直接设计即可,不需要考虑其与其他的关系(因为本来就没有关系)

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

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

相关文章

JAVA【flowable】流程引擎详解-获取发起流程详情及表单

public WfDetailVo queryProcessDetail(String procInsId, String taskId) {WfDetailVo detailVo = new WfDetailVo();// 获取流程实例HistoricProcessInstance historicProcIns = historyService.createHistoricProcessInstanceQuery().processInstanceId(procInsId).includeP…

WinDbg配置远程调试

WinDbg配置远程调试 1、为什么需要远程调试 某些特殊的场合需要远程调试,如: ①调试特殊的程序,比如在调试全屏程序,内核。 ②需要别人帮助调试或者帮助别人调试。比如由于商业性质不能直接给你pdb和源代码。 ③还有一类就是…

Python的对象和类型

这是《Python入门经典以解决计算问题为导向的Python编程实践》34-40页的笔记,简单介绍了常见的对象类型和转化函数。 对象和类型 一、认识对象二、对象的类型(一)数字1、整数2、浮点数3、复数 (二)其他内置类型1、布尔…

原地算法求两数之和

给定一个自增序列数组,总数组中找出两个元素等于目标值,并输出元素的下标。这个题右很多解法,通过hash可以将时间复杂度降到O(n),但是需要额外开辟空间,那么原地算法非常适合解决此题,及保障时间复杂度&…

基于STM32的摇杆开关控制小恐龙游戏(附源码)

文章目录 一、 前言谷歌小恐龙 二、硬件三、软件3.1 摇杆开关3.2 OLED屏幕 四、展示五、总结 一、 前言 最近有看到别人在OLED屏幕上玩小恐龙,所幸查阅下资料,并下好源码。可惜他的源码的主控是STM32F103ZET6,用的是STM32CubeIDE&#xff0c…

C++的深拷贝和浅拷贝

浅拷贝是一种简单的拷贝方式,仅仅是复制对象的基本类型成员和指针成员的值,而不复制指针所指向的内存。这可能会导致两个对象共享相同的资源,从而引发潜在的问题,如内存泄漏、意外修改共享资源等。一般来说编译器默认帮我们实现的…

运行HGD数据集的 example.py 文件

使用HGD数据集时,需要从braindecode中调用相关的函数,但是在我的环境中运行时出现错误,现将解决过程记录,方便以后查阅。 运行HGD数据集的 example.py 文件 ModuleNotFoundError: No module named ‘braindecode.datautil.signalp…

PCL安装与配置(PCL1.8.1+MSVC2017)

上一篇安装PCL1.9.1,由于Generic Warning框一直弹出。 一、PCL1.8.1下载: 路径:PCL网址 所以我又安装了PCL1.8.1 MSVC2017 x64版本的。 二、安装 安装的步骤,和PCL安装与配置(PCL1.9.1+MSVC2017)这一篇一致。大家可以参考。 直接安装双击(PCL-1.8.1-AllInOne-msvc201…

【小趴菜前端实习日记1】

后台管理系统的模块化开发&#xff1a;vue2vueRouterElement-uiaxios 一、后台框架&#xff1a;element-ui <router-view>匹配路由二、封装侧边栏&#xff08;结合el-menu进行二次封装&#xff09;1.slideBar.vue:2.slideBarItem.vuevue中用template标签包裹循环渲染列表…

AI数字人直播平台+短视频合成平台软件系统 附带源代码包以及部署教程

AI数字人直播平台概述 AI数字人直播平台是一种基于人工智能技术的虚拟直播系统&#xff0c;它利用深度学习、自然语言处理、计算机视觉等技术&#xff0c;克隆出与真人相似的AI数字人&#xff0c;并在平台上进行直播。这些数字人不仅具有真人的外形、动作&#xff0c;而且镜头…

【vulhub靶场之thinkphp】——(5-rce)

第一步&#xff1a;打开靶场 输入开启命令 cd vulhub/thinkphp/5-rce docker-compose up -d docker-compose ps//查看开启的端口 第二步&#xff1a; 访问网址 第三步&#xff1a;漏洞利用 漏洞根本源于 thinkphp/library/think/Request.php 中method方法可以进行变量覆盖&am…

Docker如何优雅删除镜像以及容器

一、先查看镜像和容器 docker images docker ps -a 二、停止正在运行的容器&#xff08;CONTAINER ID即容器ID&#xff0c;直接复制即可&#xff09; docker stop CONTAINER ID 三、删除容器 docker rm CONTAINER ID 四、删除镜像&#xff08;IMAGE ID即镜像ID&#xff0c;同理…

25考研计算机组成原理复习·3.3主存储器与CPU的连接·3.4外部存储器

目录 主存储器与CPU的连接 存储芯片的基本结构 位扩展/字扩展 位扩展 字扩展 字位同时扩展 外部存储器 磁盘存储器 磁盘原理 磁盘设备的组成 性能指标 磁盘阵列RAID 固态硬盘 组成 &#x1f469;‍&#x1f4bb; 读写性能特性 与机械硬盘相比的特点 &#x1f…

【Linux】权限(shell外壳、文件权限、管理权限)

目录 推荐文章一、shell 外壳1 文章详解&#xff1a;秒懂shell外壳程序3.shell 外壳是什么&#xff1f;4.shell 的执行 二、用户权限1.用户类型1.1.普通用户切换 rootsu 与 su - 的区别[Linux 中su 与su - 的区别](http://t.csdnimg.cn/IlIET)su - root &#xff08;完全切换了…

20240807提取飞凌OK3588-C的IMG固件中的时钟频率link_freq和pixel_clock

20240807提取飞凌OK3588-C的IMG固件中的时钟频率link_freq和pixel_clock 2024/8/6 16:32 缘起&#xff1a;调试代码的时候边调试变修改&#xff0c;在优化MIPI CSI时钟的时候&#xff0c;越改越差&#xff01;最后变成了负优化。 现在源代码/C文件找不到了&#xff0c;但是还有…

SQL注入实例(sqli-labs/less-19)

0、初始页面 1、确定闭合字符 注入点为referer&#xff0c;闭合字符为单引号 2、爆库名 3、爆表名 4、爆列名 5、查询最终目标

笔面试编程题总结

8/6诺瓦星云 修改程序 void point(int *p){*p p[2];}; int main() {int c[] {1,2,3,4,5},*p c;point(p1);for(;p <c5;){printf("%d",*p);}return 0; }1、分隔字符串 strtok //c语言 #include <stdio.h> #include <string.h>// 函数声明 char* fin…

【合并 K 个升序链表】python刷题记录

R4-分治篇 目录 最小堆方法 分治法 ps: 如果只是数组就很好处理了 # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def mergeKLists(self, lists…

C++ GDl+ 多张图片合并生成GIF动画格式图片

使用ImageMagick多张图合成GIF。 1、工具下载安装 下载地址&#xff1a;ImageMagick – Download&#xff0c;windows下载版本如下&#xff1a; 下载后&#xff0c;安装&#xff0c;安装时选择为C/C安装动态库和头文件。 2、代码实现 附加包含目录&#xff1a;ImageMagick-7.…

Is exchanging integral and sum this way allowed?

See https://math.stackexchange.com/questions/3878856/is-exchanging-integral-and-sum-this-way-allowed#:~:textYes%2C%20and%20the%20reason%20is%20simple%20-%20the,just%20a%20whole%20lot%20of%20these%20squeezed%20together.