目录
1、数据库范式简介
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
但是数据库范式绝对不是越高越好,范式越高,意味着表越多,多表联合查询的几率就越大,SQL查询的效率就变低。
一般开发中只遵从第三范式就好,是具体情况而定。
2、应用范式优点
(1)减少数据冗余(这是最主要的好处,其他好处都是由此而附带的)
(2)消除异常(插入异常,更新异常,删除异常)
(3)让数据组织的更加和谐
3、常见范式简述
常见的范式有1NF、2NF、3NF、BCNF以及4NF。下面对这几种常见的范式进行简要分析。
1)第一范式(1NF)
特点:每一列保持原子特性,列都是基本数据项,不能够再进行分割,否则设计成一对多的实体关系。
实例:
- 学生表(学号、用户名、性别、年龄,地址)
例:陕西省西安市未央区学府中路西安工业大学
地址信息还包含省市区可以拆分
- 拆分改造后:
学生表(学号、用户名、性别、年龄、地址ID)
地址表(地址ID、省、市、区、街道、学校)
注意:不符合第一范式不能称作关系型数据库。
2)第二范式(2NF)
特点:非主属性完全依赖于主键(主要针对联合主键-->消除部分依赖)
符合第一范式的基础上,非主属性完全依赖于主关键字,如果不是完全依赖主键,应该拆分成新的实体,设计成一对多的实体关系。
示例:
- 学生选课表(学生ID、学生姓名、学生性别、课程ID、课程成绩)
主键(学生ID、课程Id)
学生姓名-》学生ID -》部分依赖
学生性别-》学生ID -》部分依赖
课程成绩-》(学生ID、课程id)-》完全依赖
- 拆分改造后:
学生表(学生ID、学生姓名、学生性别)
主键:学生ID
课程成绩表(课程ID、学生ID、成绩)
主键:(课程ID、学生ID)
由于不符合2NF,这个选课关系表会存在如下问题:
(1) 数据冗余:
同一名学生选了n门课程,姓名和性别就重复了n-1次。
(2) 更新异常:
若调整了某名同学的姓名,这位同学如果选了好多门课,数据表中所有行的姓名都要更新,否则会出现同一ID姓名不同的情况。
(3) 插入异常:
假设有一名新学生还没有选课。这样,由于还没有“课程ID”关键字,学生的个人信息也无法记录入数据库。
(4) 删除异常:假设有一名因学生考试作弊课程成绩被删除,则该学生个人信息也被删除。
3)第三范式(3NF)
特点:属性不依赖于其它非主属性(消除依赖传递)
基于第二范式的基础,非主属性只依赖于主属性。
要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。
示例:
- 学生表(学生ID、学生姓名、学生性别、学院id、学院电话)
主键:学生ID
学生姓名→学生ID
学生性别→学生ID
学院名称→学生ID
学院电话 → 学生ID → 查询学院id → 查询学院电话 - 拆分改造后:
学生表:(学生ID、学生姓名、学生性别、学院ID)主键:学生ID
学院表:(学院ID、学院名称、学院电话) 主键:学院ID
拆分改造前由于不符合3NF,这个学生选课表会存在如下问题:
(1)数据冗余
有n名学生,则学院id和学院电话就被重复了n次。
(2)更新异常
若调整了学院电话,数据表中所有行的学院电话值都要更新,否则会出现同一学院id学院电话不同的情况。有上万个学生就要改上万次。
(3)插入异常
假设有一个学院没有电话,这样,由于还没有“学院电话”关键字,学生的个人信息也无法记录入数据库。
(4)删除异常
学生毕业要删除学生信息,删除后学院的电话也没有了。
注意:一般关系型数据库满足第三范式就可以了!
4)BC范式(BCNF)
特点:每个表中只有一个候选键
基于第三范式的基础上, 每个表中只有一个候选键。(不重复的属性称为候选键)
在第三范式的基础上,数据库表中如果不存在任何字段对任一候选关键字段的传递函数依赖则符合第三范式。
示例:
- 假设仓库管理关系表为StorehouseManage(仓库ID, 存储物品ID, 管理员ID, 数量),且有一个管理员只在一个仓库工作,一个仓库只有一个管理员,一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
主键:(仓库ID,管理员ID, 存储物品ID)
(仓库ID,管理员ID, 存储物品ID) → (数量)
但是我们发现:
(仓库ID, 存储物品ID) →(管理员ID, 数量)
(管理员ID, 存储物品ID) → (仓库ID, 数量)
所以,(仓库ID, 存储物品ID)和(管理员ID, 存储物品ID)都是StorehouseManage的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID) → (管理员ID)
(管理员ID) → (仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。它会出现如下异常情况:
(1)数据冗余
由于仓库ID和管理员ID是对应的,所以可以只存一个仓库ID就可以找到物品数量,没有必要再存管理员ID。要一个就行了。
(2)删除异常
当仓库被清空后,所有”存储物品ID”和”数量”信息被删除的同时,”仓库ID”和”管理员ID”信息也被删除了。
(3)插入异常
当仓库没有存储任何物品时,无法给仓库分配管理员。
(4)更新异常
如果仓库换了管理员,则表中所有行的管理员ID都要修改。
把仓库管理关系表分解为二个关系表:
仓库管理:StorehouseManage(仓库ID, 管理员ID);
仓库:Storehouse(仓库ID, 存储物品ID, )。
这样的数据库表是符合BCNF范式的,消除了删除异常、插入异常和更新异常。
5)第四范式(4NF)
特点:消除表中的多值依赖
基于BC范式的基础上,消除表中的多值依赖,也就是说可以减少维护数据一致性的工作。
示例:
- 课程表
课程id | 教材id | 课程名称 |
1 | 1 | 数学 |
2 | 2 | 语文 |
- 教材表
教材id | 教材名称 |
1 | 人教版数学,苏教版数学 |
2 | 人教版语文,苏教版语文 |
这样两本一个教材id就对应两个出版社教材,只有教材ID就说不清楚了。修改办法如下
- 课程表
课程id | 教材id | 课程名称 |
1 | 102 | 数学 |
2 | 201 | 语文 |
- 教材表
教材id | 教材名称 |
101 | 人教版数学 |
102 | 苏教版数学 |
201 | 人教版语文 |
202 | 苏教版语文 |
4、存在的问题
从上面对于数据库范式进行分解的过程中不难看出,应用的范式越高,表越多。表多会带来很多问题:
(1)查询时需要连接多个表,增加了SQL查询的复杂度
(2)查询时需要连接多个表,降低了数据库查询性能
因此,并不是应用的范式越高越好,要看实际情况而定。第三范式已经很大程度上减少了数据冗余,并且基本预防了数据插入异常,更新异常,和删除异常了。