开篇
有时候理论这东西真的是一直处于学了忘,忘了学,学了忘这种死循环中。一直没有什么办法去跳脱出来。这不,今天又啃起数据库范式来了。
概要
范式:是符合某一级别的关系模式的集合。
数据库范式:再设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数控冗余越小。
所谓的范式,个人理解的范式就像银行的客户评级体系一般。
如:一个客户办了银行卡,并且一年内的流水小于50k的,那么该客户可以申请为普通客户。如果一个客户一年内流水小于150k的,那该客户可以申请为VIP客户。同理balabala
如此,这个流水额度评断客户级别即范式。高级别的范式是符合低级别范式的,反之则不行。就像VIP客户可以申请为普通客户,但是普通客户不能申请为VIP客户。
范式简介
目前数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF,又称为完美范式)。一般来说,数据库只需要满足第三范式就好了,再高也就是BCNF了。
范式介绍
第一范式
数据库表中的所有字段值都是不可拆分的原子数据项。
现在绝大部分关系型数据库在建表的时候就已经保证了 1NF 。
如下图就是不符合 1NF 的要求:
如下就是符合 1NF 要求的设计:
如果只是满足 1NF 要求,那么数据库中必定还会存在许多冗余数据。
如上表中的冗余数据过多,班主任信息在同个班级的学生下都存储了一份,这是不必要的。所以我们可以根据第二范式来减少冗余。
第二范式
在 1NF 的基础上,非码属性必须完全依赖于候选码。(关于候选码,主属性介绍)
要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性
用人话来说就是必须有主键(或者联合主键),而且可以根据这个主键区分出每一条记录。如果是联合主键的话,那么不能只根据联合中的其中一个字段区分出每一条记录,一定要是组合后的主键才能区分。
举个例子:在一个学校里面,老师要通过广播找到学生“张伟”,但是呢,好巧不巧的这个学校正好有3个张伟,所以老师就不能直接用名字来作为通知对应的学生,而是可以说“学号为xxxxx的同学到教务处来一下”或者说“xxx年级xxx班的张伟同学到教务处来一下”。
这里的学号就是主键,而xxx年级+xxx班+张伟 就是联合主键。
在 MySQL InnoDB 存储引擎中,是必须要有主键的,即使用户没有设置主键,MySQL 也会建立一个隐藏的主键。
第三范式(来自百度百科,个人以为这段解释非常易懂)
在2NF基础上,任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。
例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性,也就是在满足2NF的基础上,任何非主属性不得传递依赖于主属性。
BCNF
在3NF基础上,任何非主属性不能对主键子集依赖(在3NF基础上消除对主码子集的依赖)
- 所有非主属性对每一个码都是完全函数依赖。
- 所有主属性对每一个不包含它的码也是完全函数依赖。
- 没有任何属性完全函数依赖于非码的任何一组属性。
看如下例子 :
学生 | 老师 | 课程 |
---|---|---|
王小明 | 科斯 | 数据结构 |
假设每个老师只教授一门课程。
则候选码有:
(学生,老师) -> 课程
(学生,课程) -> 老师
这两个码由两个属性组成,而且它们是相互交叉的关系,所以不存在传递依赖,所以符合 3NF 。
但是由于 教师 -> 课程,(主键的一部分被另一部分决定,即不符合 BCNF 中的第二条约束),所以不符合 BCNF 。
可以改成如下两张表即符合 BCNF :
学生 | 老师 |
---|---|
王小明 | 科斯 |
教师信息表:
老师 | 课程 |
---|---|
科斯 | 数据结构 |
关于候选键/码,主键,主属性的介绍:
参考:
如何解释关系数据库的第一第二第三范式? - 刘慰的回答 - 知乎