数据库学习--范式与规范化
我们都知道数据库设计中有一个比较重要的就是范式。可以说范式这让很多人头痛,不知所云。那么范式到底是什么呢?下面一起来学习下。
范式与规范化
首先我们肯定要对范式有一个比较笼统的了解:范式
是什么。
范式
是为了在设计数据库的时候,让数据表结构更加合理的一种规范
。也就是说,我们依据范式设计的数据表会让我们后面对数据表的操作更加简单与合理。
我们所说的范式也是分等级的,按照需要满足的要求从低到高依次是:第一范式
、第二范式
、第三范式
、BC范式
、第四范式
、第五范式(又称完美范式)
。
但是一般来说,只需要满足第三范式就足够了,所以下面我只对前三个范式和BC范式做说明。
既然范式是分等级
的,而在后面的学习中我们会知道,每一个高一级的范式,都是在低一级范式的基础上完善
而来的,那么就有人给我们这个完善
的过程起了个名字,就叫规范化
。
通过规范化,我们将使我们的表结构逐步满足第三范式甚至是更高级别的范式。
范式的分级
第一范式
第一范式:
最低要求的范式。它是针对数据表中具体的某一列
来说的,强调了一列的原子性
。也就是说,这一列所代表的属性是不可分的。
比如下面的例子:
上面的数据表就是一个不符合第一范式的例子,这里讲电话认为是包含了手机和座机两种类型,所以,电话
这个属性就是可分的,也就不属于第一范式。
将上面的数据表进行规范化后,形成符合第一范式的表结构应该是这样的:
第二范式
第二范式:
首先就是需要满足第一范式
,然后在此的基础上, 要求除了主键之外的所有属性都必须完全依赖
于主键,而不能只依赖于主键的一部分。它规定了数据的唯一性
。
思考上面的话,发下它需要两步:
1.所有属性都依赖
于主键
2.所有依赖都是完全依赖
依赖
好说,就是强调唯一确定
的关系。那么完全依赖
是什么意思呢?这个用存在联合主键
的表来解释更容易理解:
比如有如下的表结构学生课程表
:
在上面的数据表中,需要使用(学号,课程号)
来作为联合主键。
首先来验证第一点:姓名
和成绩
都`依赖于主键,主键确定了,姓名和成绩也就确定了。
然后来验证第二点:成绩
是完全依赖
于主键的,只有确定了是哪个学生的哪门课,成绩才能确定;
但是姓名
就不是完全依赖于主键了,只要学号确定了,就可以唯一确定姓名了,所以,姓名
是部分依赖
于主键的。
不满足第二点,所以上面的表也就不符合第二范式。
那么,这样的数据表结构会有什么问题呢?
- 数据冗余:当一个学生有多门课的成绩的时候,就会出现每条数据中都有
姓名
这么一个重复的字段- 删除异常:当删除了一个学生所有的成绩后,这个学生也就没有了
- 插入异常:在学期开始的时候,所有学生都还没有选课,这时,就没有办法保存学生的信息
- 更新异常:在输入姓名的时候,错别字,写错了,需要修改,这时候就需要多条记录
那么如何解决这个问题呢?正确的做法是应该将上面的表拆分成三个表:
学生课程表:
学生表
课程表
第三范式
第三范式:
也是在第一范式的基础上定义的,同时,任何非主属性
(除主键)不依赖于其他非主属性,且不存在传递依赖(a->b,b->c,则a->c)。它解决了数据表的冗余性
。
简单点来说,就是每个属性都被主键直接
约束。
看一下下面的例子:
学院编号会被学号所唯一确定,然后学院名称又被学院编号唯一确定,即:
学号->学院编号->学院名称
这就出现了传递依赖,所以不属于第三范式。
那么这样会有什么问题呢?同第二范式解决的问题类似,会出现数据冗余、更新异常
等的问题:
1.添加一个学院,每个学生都需要输入学院名称
这个字段
2.修改学院时,每个学生的记录都需要修改,否则就会出现数据不一致
解决办法就是将上面的表拆成两个子表:
学生表
学员表
BC范式
BC范式
:它是在第三范式的基础上定义的,是一个用的稍微少一点的概念,在上面的讲第二范式
的时候,我们提到了联合主键
的概念,BC范式
就是对它进行约束:主属性不能依赖于主属性(联合主键中的属性)
因为这个概念用的比较少,这里就不做过多的介绍了。
范式的作用
通过上面对几个范式的介绍,也可以看出,范式
帮助我们解决了在插入、删除、更新的操作的时候遇到的问题,使我们在操作数据库的时候方便而且准确。
范式
的出现,使数据表结构更加规范,也使操作数据表更加容易。
但是,是不是满足级别越高范式就越好呢?其实也不然。
我们在解决上面范式问题的时候,所用到的方法,无一例外,全是用增加数据表的数量
,然后建立表之间的关联实现的。
而在我们实际的项目种,很多时候都是为了处理查询
问题,这时候,进行某个查询就很有可能是多表的关联查询,根据实际项目中的经验我们也能知道,关联查询还是比较费事的,所以查询就显得效率有点低
了,而且操作的难度也更大。
这时候,如果能够有个别的冗余数据,就会使查询有意向不到的效果。
所以,在使用范式的时候,还是要结合考虑实际的需求,在查询的需求很高的时候,不妨添加以两个冗余的字段,来减小查询的压力;而如果删除和更新的需求较高的时候,还是按照范式的规范来进行比较好。
相关参考:
https://segmentfault.com/a/11...
https://blog.csdn.net/Dream_a...
https://coach.iteye.com/blog/...
https://blog.csdn.net/zhufuyi...