首页 > 数据库 >数据库的范式设计

数据库的范式设计

时间:2023-07-13 19:25:20浏览次数:57  
标签:范式 数据库 学生 185cm student 设计 主键

数据库的范式设计

原文链接:(三)MySQL之库表设计篇:一、二、三、四、五范式、BC范式与反范式详解! - 掘金 (juejin.cn)

【一】引言

  • MySQL的库表设计,在很多时候我们都是根据我们自己的个人喜好和习惯创建出来的,在前期的设计中总是会有考虑不到的地方,对于库表结构的划分也并不明确

  • 这也就导致了我们在开发过程中,代码写着写着就会想去重构表的结构,甚至需要大面积的重构多张表结构

  • 这种随心所欲的设计方式,无疑给开发造成了很大困扰,令我们很头疼。

  • 但实际上设计DB库表结构时,也有一些共同需要遵守的规范,这些规范在数据库设计中被称为“范式”,理解并掌握这些设计时的规范,能让咱们在项目之初,设计的库表结构更为合理且优雅。

  • 数据库范式中,声名远扬的有三大范式,但除此之外也有一些其他设计规范,如:

    • 数据库三大范式(1NF、2NF、3NF

    • 第四范式(4NF)和第五范式:完美范式(5NF

    • 巴斯-科德范式(BCNF

    • 反范式设计

【一】数据库三大范式

  • 范式(Normal Form)在前面也提到过,它就是指设计数据库时要遵守的一些原则
  • 而数据库的三大范式,相信诸位在学习数据库知识时也定然接触过。
  • 三大范式之间,它们是递进的关系,也就是后续的范式都基于前一个范式的基础上推行,就好比下面这句话:
今天我要先炒菜,然后吃饭,最后洗碗。
  • 炒菜、吃饭、洗碗三者也属于递进关系
    • 后者都建立在前者之上,其顺序不能颠倒
    • 比如先吃饭再炒菜,这必然是行不通的。
  • 数据库的三大范式也一样,第二范式必须建立在第一范式的基础之上,如若设计的库表第一范式都不满足,那定然是无法满足第二范式的。

写在前面的话:

​ 其实对于数据库三范式相关的资料,网上也有很多很多,但大部分资料都涉及了太多的概念,通篇看下来也很难让人理解

​ 因此下述的三范式则会结合具体的设计实例来让诸位彻底理解三范式。

【1】第一范式(1NF)

  • 库表设计时的第一范式,主要是为了确保原子性的,也就是存储的数据具备不可再分性
  • 这话咋理解呢?上个案例:
SELECT * FROM `zz_student`;
+----------------------+--------+-------+
| student              | course | score |
+----------------------+--------+-------+
| 竹子,男,185cm      | 语文   |    95 |
| 竹子,男,185cm      | 数学   |   100 |
| 竹子,男,185cm      | 英语   |    88 |
| 熊猫,女,170cm      | 语文   |    99 |
| 熊猫,女,170cm      | 数学   |    90 |
| 熊猫,女,170cm      | 英语   |    95 |
+----------------------+--------+-------+
  • 在上述的学生表中,其中有一个student学生列,这一列存储的数据则明显不符合第一范式:
    • 原子性的规定,因为这一列的数据还可以再拆分为姓名、性别、身高三项数据
  • 因此为了符合第一范式,应该将表结构更改为:
+--------------+-------------+----------------+--------+-------+
| student_name | student_sex | student_height | course | score |
+--------------+-------------+----------------+--------+-------+
| 竹子         | 男          | 185cm          | 语文   |    95 |
| 竹子         | 男          | 185cm          | 数学   |   100 |
| 竹子         | 男          | 185cm          | 英语   |    88 |
| 熊猫         | 女          | 170cm          | 语文   |    99 |
| 熊猫         | 女          | 170cm          | 数学   |    90 |
| 熊猫         | 女          | 170cm          | 英语   |    95 |
+--------------+-------------+----------------+--------+-------+
  • student这一列数据,分别拆分为姓名、性别、身高三列,然后分别存储对应的数据才合理
  • 通过这样的优化后,此时zz_student这张表则符合了数据库设计的第一范式。

那此刻思考一下:如果不去拆分列满足第一范式,会造成什么影响呢?

  • 客户端语言和表之间无法很好的生成映射关系。
  • 查询到数据后,需要处理数据时,还需要对student字段进行额外拆分。
  • 插入数据时,对于第一个字段的值还需要先拼装后才能进行写入。

简单来说

​ 如果按照原本那张形式去做业务开发,显然操作起来会更加麻烦且复杂一些

​ 但第一范式的原子性,除开对列级别生效之外,行级别的数据也是同理

​ 也就是每一行数据之间是互不影响的,都是独立的一个整体。

【2】第二范式(2NF)

  • 上述的第一范式还是比较容易理解
  • 紧接着来看看第二范式
    • 第二范式的要求表中的所有列,其数据都必须依赖于主键
  • 也就是一张表只存储同一类型的数据,不能有任何一列数据与主键没有关系
  • 还是上面的那张表数据为例:
+--------------+-------------+----------------+--------+-------+
| student_name | student_sex | student_height | course | score |
+--------------+-------------+----------------+--------+-------+
| 竹子         | 男          | 185cm          | 语文   |    95 |
| 竹子         | 男          | 185cm          | 数学   |   100 |
| 竹子         | 男          | 185cm          | 英语   |    88 |
| 熊猫         | 女          | 170cm          | 语文   |    99 |
| 熊猫         | 女          | 170cm          | 数学   |    90 |
| 熊猫         | 女          | 170cm          | 英语   |    95 |
+--------------+-------------+----------------+--------+-------+
  • 虽然此时已经满足了数据库的第一范式,但此刻观察course课程、score分数这两列数据,跟前面的几列数据实际上依赖关系并不大,同时也由于这样的结构,导致前面几列的数据出现了大量冗余
  • 所以此时可以再次拆分一下表结构:
SELECT * FROM `zz_student`;
+------------+--------+------+--------+--------------+--------------+
| student_id | name   | sex  | height | department   | dean         |
+------------+--------+------+--------+--------------+--------------+
|          1 | 竹子   | 男   | 185cm  | 计算机系     | 竹子老大     |
|          2 | 熊猫   | 女   | 170cm  | 金融系       | 熊猫老大     |
+------------+--------+------+--------+--------------+--------------+
SELECT * FROM `zz_course`;
+-----------+-------------+
| course_id | course_name |
+-----------+-------------+
|         1 | 语文        |
|         2 | 数学        |
|         3 | 英语        |
+-----------+-------------+
SELECT * FROM `zz_score`;
+----------+------------+-----------+-------+
| score_id | student_id | course_id | score |
+----------+------------+-----------+-------+
|        1 |          1 |         1 |    95 |
|        2 |          1 |         2 |   100 |
|        3 |          1 |         3 |    88 |
|        4 |          2 |         1 |    99 |
|        5 |          2 |         2 |    90 |
|        6 |          2 |         3 |    95 |
+----------+------------+-----------+-------+
  • 经过上述结构优化后,之前的一张表此时被我们拆分成学生表、课程表、成绩表三张
  • 每张表中的id字段作为主键,其他字段都依赖这个主键。
  • 无论在那张表中,都可以通过id主键确定其他字段的信息。

主键可以不用id,但最好是自增的主键ID,这跟索引有关,后续索引篇详细讲解。

  • 此时再将目光看到先后两张学生表
    • 原本的学生表有六条学生记录,其中有四条是冗余数据
    • 此时的学生表则只有两条数据,同时这张学生表中只存储学生信息相关的数据。
  • 经过本次结构优化后,每张表的业务属性都具备“唯一性”,也就是每张表都只会描述了“一件事情”,不会存在一张表中会出现两个业务属性(例如之前的学生表包含了学生信息和课程成绩)。

【3】第三范式(3NF)

  • 前面已经对第一范式、第二范式进行了直观阐述
  • 接下来聊一聊数据库的第三范式
    • 第三范式要求表中每一列数据不能与主键之外的字段有直接关系
  • 怎么理解呢?基于上述的例子:
+------------+--------+------+--------+--------------+--------------+
| student_id | name   | sex  | height | department   | dean         |
+------------+--------+------+--------+--------------+--------------+
|          1 | 竹子   | 男   | 185cm  | 计算机系     | 竹子老大     |
|          2 | 熊猫   | 女   | 170cm  | 金融系       | 熊猫老大     |
+------------+--------+------+--------+--------------+--------------+
  • 比如这张学生表,目前即符合第一范式,也符合第二范式
    • 但看最后的两个字段,department表示当前学生所属的院校,dean则表示这个院系的院长是谁。
  • 一般来说,一个学生的院长是谁,首先是取决于学生所在的院系的
    • 因此最后的dean字段明显与department字段存在依赖关系
  • 因此需要进一步调整表结构:
SELECT * FROM `department`;
+---------------+-----------------+-----------------+
| department_id | department_name | department_dean |
+---------------+-----------------+-----------------+
|             1 | 计算机系        | 竹子老大        |
|             2 | 金融系          | 熊猫老大        |
+---------------+-----------------+-----------------+
SELECT * FROM `zz_student`;
+------------+--------+------+--------+---------------+
| student_id | name   | sex  | height | department_id |
+------------+--------+------+--------+---------------+
|          1 | 竹子   | 男   | 185cm  |             1 |
|          2 | 熊猫   | 女   | 170cm  |             2 |
+------------+--------+------+--------+---------------+
  • 经过进一步的结构优化后
    • 又将原本的学生表拆为了院系表、学生表两张
      • 学生表中则是只存储一个院系ID,由院系表存储院系相关的所有数据。
    • 至此,学生表中的每个非主键字段与其他非主键字段之间,都是相互独立的,之间不会再存在任何依赖性,所有的字段都依赖于主键。

那这里为什么要调整呢?不调整不行吗?还真不行,来简单思考一下不调整结构的情况下会发生什么问题:

  • 当一个院系的院长换人后,需要同时修改学生表中的多条数据。
  • 当一个院长离职后,需要删除该院长的记录,会同时删除多条学生信息。
  • ......

也就是如果设计的表结构,无法满足第三范式,在操作表时就会出现异常,使得整个表较难维护。

【4】数据库三范式小结

总结如下

  • 到这里就已经将库表设计的三范式做了直观阐述:

    • 第一范式:

      • 确保原子性,表中每一个列数据都必须是不可再分的字段。
    • 第二范式:

      • 确保唯一性,每张表都只描述一种业务属性,一张表只描述一件事。
    • 第三范式:

      • 确保独立性,表中除主键外,每个字段之间不存在任何依赖,都是独立的。

必要性

  • 经过三范式的示例后,数据库中的表数量也逐渐多了起来,似乎设计符合三范式的库表结构,反而更加麻烦了对吗?

  • 答案并非如此,因为在没有按照范式设计时,会存在几个问题:

    • 整张表数据比较冗余,同一个学生信息会出现多条。

    • 表结构特别臃肿,不易于操作,要新增一个学生信息时,需添加大量数据。

    • 需要更新其他业务属性的数据时,比如院系院长换人了,需要修改所有学生的记录。

  • 但按照三范式将表结构拆开后,假设要新增一条学生数据,就只需要插入学生相关的信息即可

  • 同时如果某个院系的院长换人了,只需要修改院系表中的院长就行,学生表中的数据无需发生任何更改。

因此,经过三范式的设计优化后,整个库中的所有表结构,会显得更为优雅,灵活性也会更强。

标签:范式,数据库,学生,185cm,student,设计,主键
From: https://www.cnblogs.com/dream-ze/p/17551853.html

相关文章

  • 设计模式-建造者模式在Java中使用示例
    场景建造者模式复杂对象的组装与创建没有人买车会只买一个轮胎或者方向盘,大家买的都是一辆包含轮胎、方向盘和发动机等多个部件的完整汽车。如何将这些部件组装成一辆完整的汽车并返回给用户,这是建造者模式需要解决的问题。建造者模式又称为生成器模式,它是一种较为复杂、使用......
  • 常用关系型数据库(草稿)
     仅针对mysql、sqlserver、oracle、人大金仓、达梦数据库数据库是一组文件,位于磁盘,用于存储数据表名/字段规范/*表名/字段长度:Oracle:最多30个字符SQLServer:最多128个字符MySQL:最多64个字符​表名规范:1.以字母开头,只能使用A-Z、a-z、0-9、[#$不建议]MySQL中......
  • python之数据库: 约束条件
    约束条件"""约束条件的意思是,在数据类型的基础上再添加限制条件"""1.unsigned去除符号createtablet1(idintunsigned);2.zerofill3.notnull非空createtablet2(idint,namevarchar(16));以上例子15:#在mysql中,''和null不一样createtablet3(idi......
  • DB2数据库怎么查询到多条,但只取首行数据
    DB2数据库怎么查询到多条,但只取首行数据select*fromemployeeFETCHFIRST1ROWSONLY;解释:employee假设是一个数据库表,也就是说在你的查询语句后边加上FETCHFIRST1ROWSONLY就可以了。......
  • 【ChatGPT系列】数据库设计范式与最佳实践
    [本文出自天外归云的博客园]数据库范式一共有四个范式,分别是第一范式(1NF)、第二范式(2NF)、第三范式(3NF)和第四范式(4NF)。每个范式都有一些规则和规范,用于确保关系型数据库中的数据具有一定的一致性、完整性和有效性。随着范式级别的提高,规则和规范也越来越严格,要求数据库中的数据更加......
  • 助教工作总结(高级语言程序设计C语言)
    一、助教工作的具体职责和任务1、与老师的配合:协助老师指导两次课程设计协助老师指导蓝桥杯、天梯赛2、与课程其他助教的配合:共同解决同学们课后的疑问并将出现的重点问题反馈给老师安排大作业并进行相应的指导,最后进行批改评分将最终成绩反馈给老师一起挑选有深度的题......
  • 如何实现saas 权限架构设计的具体操作步骤
    SaaS权限架构设计概述在SaaS(SoftwareasaService)应用中,权限管理是一项非常重要的功能。它允许系统管理员对用户的访问和操作进行精细的控制,确保系统的安全性和数据的隔离性。本文将介绍实现SaaS权限架构设计的流程和每一步需要做的事情,以及相应的代码示例。流程图下面的表格......
  • 数据库事务
    数据库事务四大特性1、原子性(Atomicity)即使事务的一部分失败,整个事务也会失败。这样,每个事务都必须100%成功才能成功提交到数据库。2、一致性系统要么将事务写入数据库(将数据库从一种有效状态更改为另一种状态),要么还原事务。3、隔离性隔离性是当多个用户并发访问数据......
  • PHP 生成数据库的 markdown 字段说明文档,支持 mysql,postgresql
    安装composerrequirepeng49/db2markdown命令行使用phpvendor/bin/db2markdown输入数据库的地址(host),端口(port)用户名,密码,要导出的表,默认是*,生成所有表的文档,指定多个表明用逗号隔开,如:table1,table2$phpsrc/bin/db2markdownpleaseenterthedb(1mys......
  • 设计原则
    面向对象设计的SOLID五大原则【S】单一职责原则(SingleResponsibilityPrinciple,SRP)【O】开闭原则(OpenClosedPrinciple,OCP)【L】里氏代换原则(LiskovSubstitutionPrinciple,LSP)【I】接口隔离原则(InterfaceSegregationPrinciple,ISP)【D】依赖倒转原则(DependencyInversi......