数据库基础(五)——数据库范式
前言
数据库范式的概念虽然很枯燥但是理解后就会一直记在脑子里,所以本篇笔记就当做是看一个很枯燥的课文吧。
为什么需要规范数据库中的数据格式?其实很简单,数据不加以规范的话会在不同的表中出现相同的字段,这样会造成存储空间浪费以及数据冗余的情况出现;如果我们大量使用外键做表间连接,还有可能出现数据冲突,修改数据操作异常等情况(先说明一下,个人从宏观角度将数据库的CRUD操作分类为修改和查询操作,其中修改操作包括修改、删除、插入。以后除非区分CRUD外,本人博客皆统称为修改和查询操作)。
概述
数据库的范式包括以下几种:
-
第一范式(1NF):最基本的范式,表中每个字段必须不可再分,即字段中的值必须确定为独立的值且只能表达一个概念;
换而言之就是不能出现一个字段中出现两种含义的数据,如下图所示:
上图中展示的就是不正确的字段。
-
第二范式(2NF):在1NF基础上,消除了所有非主属性(除主键外的字段)对于主键的部分函数依赖:
举个例子,如果我们数据表中的某一个字段中存放的数据中有一个主键,那么所有的字段都应该依赖且唯一依赖主键,不能存在重复的字段或者数据,如果有重复的字段或者数据那么就将表拆分成为两个表;
即,表中的一行数据只有一个工作,身份证号为主键的话,那么年龄、地区、性别等信息都要在这个表中,同时,入学信息等就不能和上述信息放在同一个表中,因为我们需要存储学生在校信息,这种情况就要把它们拆成两个表。
-
第三范式(3NF)
以学生信息表举例子,我们每个学生的学号都是独一无二的(具体请参考高校对于学号的规定,在此不做赘述),我们完全可以使用学生的学号来做主键。同时,学号的组成是由我们的入学年份、系别、专业、班级、以及班级中的顺位来组成我们的学号,所以我们可以通过学号来辨别该学生在校的相关信息,所以这些在校信息字段都依赖于我们设定为主键的学号,这样就符合3NF;
如果我们不把学号当做主键,而是通过其他方式来生成了主键,比如身份证号码,这个时候我们就会出现学号依赖于身份证号,因为身份证号是唯一的,学号也是唯一的。同时,我们的在校信息等依赖于学号,这样就出现了传递依赖
-
俗称的3.5范式(BCNF):
在说明3.5范式(BC范式)之前需要先了解一个概念,即主属性、主键的区别:
- 主键:即我们进场会遇到的,一张表中唯一标识一行数据的字段,每个表中主键只能有一个;
- 主属性:即联合主键(候选码),候选码可以有多个。某些复杂的数据库中,一个字段的值不仅仅依赖主键产生,他需要多个字段来决定它的最终值,这个时候我们就会出现多个候选码(联合主键)的情况。
我们的BCNF就是消除了主属性(候选码)对主键的部分依赖和传递依赖,即类似于3NF中的规范,只是将3NF中对于普通字段和主键的规范用在了主属性和主键中。
-
第四范式(4NF):
现今最高形态的数据库规范,此规范中禁止了字段中一对多的关系,只允许一对一,通俗理解为在3NF的基础上,我们将所有字段仅依赖于主键,普通字段之间不存在依赖关系。
说到这里其实大家并不是很理解,数据库范式为什么这么复杂。其实大家有没有发现,我们范式的更新迭代在一步一步消除字段与字段之间的关系。
前文说到过数据库设计规范,讲的是表与表之间的关系,这篇笔记说明的是表中字段与字段的关系。这两篇笔记都致力于减少各个元数据之间的物理关系,才有更加灵活的逻辑关系来连接。说到这里我们可以回想一下NOSQL的概念与优势。
言尽于此,感兴趣的同学可以自己去看看书、博客等资料,自己思考。
总结
最近几篇笔记都很短,主要因为这一部分知识点枯燥且难懂(绝对不是博主懒)。
本篇笔记中记录的范式中,并不是等级越高的表就越好,大家都知道鱼和熊掌不可兼得,我们为了业务明确将表拆成了多个表后会出现联表查询效率过低的情况,虽然业务逻辑更加清晰,但是会造成性能低下。这个时候我们就需要考虑在某些表中加入一些冗余字段,虽然会造成空间浪费且业务复杂一些,但是通过空间换取时间来提高效率。