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

【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 语句将旧表插入到目标表

在这里插入图片描述

http://www.xdnf.cn/news/6276.html

相关文章:

  • 穿透工具如何保证信息安全?
  • 小白入门:GitHub 远程仓库使用全攻略
  • Stack overflow
  • CSS3 变形
  • 蓝桥杯12届国B 123
  • 机器学习——朴素贝叶斯练习题
  • Docker部署单节点Elasticsearch
  • 互联网大厂Java求职面试实战:Spring Boot到微服务全景解析
  • 【C++】解析C++面向对象三要素:封装、继承与多态实现机制
  • 【漫话机器学习系列】260.在前向神经网络中初始权重(Initializing Weights In Feedforward Neural Networks)
  • 知从科技闪耀2025上海车展:以创新驱动未来出行新篇章
  • Logistics | Days of Inventory vs. Stock Days 【待续】
  • 2.安卓逆向2-adb指令
  • MIFARE DESFire Light 卡C#读写更改卡片密钥源码
  • SLAM定位与地图构建
  • 【专栏启动】开篇:为什么是 Django + Vue3?测试平台的技术选型与架构蓝图
  • 通用软件项目技术报告 - 第一章节检测 - 参考答案
  • DeepSeek执行流程加速指南:跨框架转换与编译优化的核心策略全解析
  • Day118 | 灵神 | 二叉树 | 删点成林
  • 缺乏对新技术的评估和引入机制,如何建立
  • 【C++】set和multiset的常用接口详解
  • 答题pk小程序道具卡的获取与应用
  • yarn任务筛选spark任务,判断内存/CPU使用超过限制任务
  • 【物联网】基于树莓派的物联网开发【3】——最新镜像下载和烧录
  • 【iOS】源码阅读(四)——isa与类关联的原理
  • 怎么样制作网站?
  • redis是内存级缓存吗
  • the request was rejected because no multipart boundary was found
  • Python-Django系列—日志
  • 中间件-MQ常见问题