当前位置: 首页 > news >正文

【MySQL】第四弹——表的CRUD进阶(二)数据库设计

文章目录

  • 🌟范式
  • 🌟表的设计
    • 💫第一范式 1NF
      • 🪐反例
      • 🪐正例
    • 💫第二范式 2NF
      • 🪐反例
      • 🪐正例
    • 💫第三范式 3NF
      • 🪐反例
      • 🪐正例
    • 💫表的设计方法
      • 🛰️一对一关系
      • 🛰️一对多关系
      • 🛰️多对多关系
  • 🌟表设计总结
    • 💫新增-插入查询

🌟范式

数据库的范式是⼀组规则。在设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式

关系数据库有六种范式:第⼀范式(1NF)、第⼆范式(2NF)、第三范式(3NF)、巴斯-科德
范式(BCNF)、第四范式(4NF)和第五范式(5NF,⼜称完美范式),越⾼的范式数据库冗余越⼩。然⽽,普遍认为范式越⾼虽然对数据关系有更好的约束性,但也可能导致数据库IO更繁忙,因此在实际应⽤中,数据库设计通常只需满⾜第三范式即可

总结:范式描述的就是数据关系模型,一对一关系,一对多关系,多对多关系

现在有一个学生教务系统
学生,学号,课程,班级

  • 一个学生 只能有一个学号,一个学号只能是一个学生(一对一)
  • 一个学生只属于一个班级,一个班级可以包含多个学生(一对多)
  • 一个学生可以选择多门课程,一个课程也可以包含多个学生(多对多)

🌟表的设计

  • 根据一些实际的业务场景,来设计表,主要是确定数据库中有几个表,每个表是做什么的,每个表有哪些字段

OOA 面向对象分析–>OOD 面向对象设计–>OOP 面向对象编程

具体步骤
1.从需求中获得,类对应到数据库中的实体,实体在数据空中就表现为一张一张的表,类中的属性就对应着表中的字段(列)
2.确定类与类之间的关系
3.使用SQL去创建具体的表

设计表的时候会遵守的规则,这样的规则我们称之为三大范式

💫第一范式 1NF

关系型数据库的一个最基本要求,不满足第一范式不可以称为关系型数据库

  • 数据库表的每⼀列都是不可分割的原⼦数据项,而不能是集合,数组,对象,即表里的字段不可再进行拆分

🪐反例

  • 举个第一范式的反例

有一个学生表
学号,姓名,年龄,班级名,学校
这些字段前四个都可以用数据类型来表示
bigint ,varchar,int,varchar
但是学校这个字段并没有数据类型来表示学校
学校还可以拆分成:学校名称,学校网址…
拆分后就可以用varchar数据类型表示

像这样可以继续拆分的字段在关系型数据库中是绝对不允许的

🪐正例

  • 第一范式正例

学生表
学号,姓名,年龄,班级编号,学校名称,学校网址

虽然这样不符合数据库设计的规范,但是每一列是不可再拆分的,最起码可以表明一个学生和班级学校的关系

每一个字段都可以有一个数据类型表示,那么这个表就天然满足第一范式

💫第二范式 2NF

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

在这里插入图片描述

  • 场景:学生可以选修课程,课程有对应的学分,学生考试之后会针对每一门选修课生成相应的成绩
  • 使用数据库中的表记录学生的成绩

🪐反例

  • 第二范式反例
    在这里插入图片描述

学生相关的信息通过学号确定
学分相关的信息通过课程确定
成绩通过 学生课程共同区分.一个学生选修的课程,经过一次考试之后会生成成绩

也就是说这个表中的 学生和课程作为复合主键来确定一个学生当前选修课的成绩

学生的姓名,年龄和课程没有关系,即姓名,年龄只依赖于学号,不依赖与课程
学分与学生没关系,即学分只依赖于课程,不依赖与学生

这里的依赖关系一定要梳理清楚

由两个或多个关键字段决定一条记录,如果一行数据中的有些字段只与关键字段中的一个有关系,我们就把这种情况叫做他存在部分函数依赖,那么这个表就不满足第二范式

我们借用这个反例继续完成这个数据表,看看可能会出现的问题

在这里插入图片描述

  • 不满足第二范式可能会出现的问题:
  1. 数据冗余
    学生姓名、年龄、学分这些字段都是重复出现,造成了大量的数据冗余

  2. 更新异常
    若需要对MYSQL的学分进行调整,那么就需要更新所有记录中关于MYSQL的记录,如果一旦数据库出现异常,某些记录更新成功,某些更新失败,就会造成数据表同一门课程不同学分,数据不一致

  3. 插入异常
    学校新开设了一门课程,已经定义好学分了,但是目前这样的表设计,每一门课程与学生的考试是对应关系,只有进行考试才会生成一条关于课程的成绩记录,记录里保存了课程的学分,也就是说,新课程在之前的数据库中没有相应的记录.因为学生成绩为空时记录没有意义

  4. 删除异常
    毕业的学生需要全部删除,删除记录的同时,也可能把课程对应的学分全部删除,导致一段时间内,数据中没有课程和学分相应的信息

🪐正例

  • 第二范式正例
    在这里插入图片描述
    这样的表设计,每张表都有非主键字段,都强依赖于主键,满足第二范式

也就是说一个表中没有复合主键(主键只有一列)那么这种表就天然满足第二范式

💫第三范式 3NF

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

场景:描述学生就读于哪个学院

🪐反例

  • 第三范式反例

在这里插入图片描述
现在要描述学生,可以很明显的判定出 学号就是学生表的主键

这个表的设计中,姓名和年龄与学号强相关
学院网址与所属学院强相关

描述清楚学生所属学院,只需要把学生和学院建立一个关联关系,此时可以看出两种强相关关系出现在同一条记录

两个强相关系存在传递现象
学号–>所属学院–>学院网址

这种传递关系称之为 传递依赖

这样的表设计不满足第三范式,因为存在传递依赖

🪐正例

  • 第三范式正例

根据学生和学院的关系,拆分为两张表即可

在这里插入图片描述
这样的表设计,两张表都依赖于自己表中的主键,学生表可以通过外键与学院之间建立关联关系

第三范式可以解决数据冗余,更新异常,插入异常,删除异常的问题

💫表的设计方法

1.在场景中找到实体
2.确定实体与实体间的关系

在这里插入图片描述

🛰️一对一关系

比如教务系统的登录界面
在这里插入图片描述

像这样的场景,一般对应着两个实体,一个实体是用户(包括学生,老师),另一个实体是账号

用户:记录个人信息,姓名,班级,QQ号,手机号
账号:登录名,密码

一个用户只能有一个账号,一个账号只能给一个用户使用,不能共享

在设计表之前先按上面的句式把实体之间的关系列出来

  • 针对一对一关系,设计表时,有两种方式

在这里插入图片描述

🛰️一对多关系

比如学生和班级之间的关系
一个学生只能存在于一个班级,一个班级中可以有多个学生

  • 创建表:

1.分别为不同的实体创建表–学生表,班级表
2.建立表与表之间的关联关系
class(class_id,name);
student(student_id,name,age,class_id);

通过学生记录中的class_id 可以表示学生在哪个班级,每个学生都关联了一个班级

🛰️多对多关系

一个学生可以选修多门课程
一门课程也可以被多名学生选修

  1. 分别创建实体表
    在这里插入图片描述

  2. 创建关系表,在关系表中为实体之间创建关联关系

在这里插入图片描述

通过关系表,就可以把学生修改的课程清楚的记录下来,这样设计同时也满足了第二范式的要求,如果要修改学生的年龄只需要修改学生表中的年龄字段即可,不会影响关系表

  • 学生选修课成绩表

1.班级表(班级编号,班级名)

create table class(
class_id bigint primary key auto_increment,
name varchar(50) not null
);

2.学生表(学生编号,学号,姓名,年龄,右键,班级编号)

create table student(
student_id bigint primary key auto_increment,
sn varchar(6) unique,
name varchar(50) not null,
mail varchar(50),
class_id bigint,
foreign key (class_id) references class(class_id)
);

3.课程表(课程编号,课程名)

create table course(
course_id bigint primary key auto_increment,
name varchar(50) not null
); 

4.成绩表(编号,学生编号,课程编号,成绩)

create table score(
score_id bigint primary key auto_increment,
student_id bigint,
course_id bigint,
score decimal(5,2),
foreign key (student_id) references student (student_id),
foreign key (course_id) references course (course_id)
);

班级表与学生表之间是一对多的关系
学生表与课程表之间是多对多的关系,通过一个关系表进行关联

🌟表设计总结

在这里插入图片描述

💫新增-插入查询

  • 插入查询结果

新建一张表,把旧表的指定列数据导入到新表中

语法:

insert into table_name [(column [,..])] select ...

在这里插入图片描述

在这里插入图片描述

  • 使用insert into select 语句将旧表插入到目标表

在这里插入图片描述

相关文章:

  • 《Python星球日记》 第78天:CV 基础与图像处理
  • 2025年黑客扫段攻击激增:如何构建智能防御体系保障业务安全?
  • R S的EMI接收机面板
  • 从 Vue3 回望 Vue2:组件设计升级——Options API vs Composition API
  • 交叉编译源码的方式移植ffmpeg-rockchip
  • 20250515配置联想笔记本电脑IdeaPad总是使用独立显卡的步骤
  • 力扣-46.全排列
  • 【QGIS二次开发】地图显示与交互-03
  • 嵌入式开发中使用 MySQL 数据库常见问题及解决办法
  • CSS3 变形
  • 行为型模式:责任链模式
  • RPA 自动化实现自动发布
  • tomcat项目重构踩坑易错点
  • 【2025最新】VSCode Cline插件配置教程:免费使用Claude 3.7提升编程效率
  • Electron 主进程中使用Worker来创建不同间隔的定时器实现过程
  • Electron 应用的升级机制详解
  • Electron详解:原理与不足
  • Windows 环境下 Docker Desktop 安装 + 汉化
  • MinerU安装(pdf转markdown、json)
  • win11平台下的docker-desktop中的volume位置问题
  • 被前男友泼汽油致残后,一个女孩经历的双重灼烧
  • MSCI中国指数5月调整:新增5只A股、1只港股
  • 智能手表眼镜等存泄密隐患,国安部提醒:严禁在涉密场所使用
  • 93岁南开退休教授陈生玺逝世,代表作《明清易代史独见》多次再版
  • 金科股份重整方案通过,正式进入重整计划执行环节
  • 韩国大选连发“五月惊奇”:在野党刚“摆脱”官司,执政党又生“内讧”