数据库设计——三范式概念+实战,范式实战
在利用三范式设计数据库的时候,以前总以为是先画完ER图,然后导出关系模式,最后用三范式去检验数据库设计的是否合理,but not!我们在一开始画ER图的时候,就应当和三范式联系起来,将错误消灭在源头。为了能最早的检验出错误,我们就要对ER图转换成关系模式的算法和三范式是如何消除冗余,避免冲突有深刻的了解,才能知道如何最早发现错误。
本文主要以机房收费系统数据库设计中的一些东西为例,结合三范式概念,简述下三范式。
一,1NF
定义:
如果关系模式R的每个关系r的属性值都是不可分的原子值,那么称R是第一范式。
简单来说,第一范式要求属性不可再分,来看一个比较常见的例子:
例如,在机房收费系统中,比如我们会遇到日期时间是该写成一个属性还是分开写呢?这时候我们就要根据第一范式来做出一个判断了,因为第一范式要求属性值不可再分,所以我们应该这样:
二,2NF
定义:
如果关系模式R是1NF,且每个非主属性完全函数依赖于候选键,那么称R是第二范式。
要明白第二范式,首先要明白什么是完全函数依赖?
完全函数依赖:
在R(U)中,如果X→Y,并且对于X的任何一个子集x,都有x→不成立,则称Y对X完全函数依赖。
如图,(X1,X2)→Y,并且,X1→Y不成立,X2→Y不成立。
但是,如果在完全函数依赖中,若X→Y,但Y不完全函数依赖于X,则称Y对X部分函数依赖。
例如,如图,此时,X1→成立,则Y部分依赖于X1X2;
综上,我们可以得出,要满足第二范式,就要让每一个非主键属性完全依赖于主键。
例如,我们在机房收费系统设计数据库的时候,对于学生表可能有过这样的设计,最开始的时候,我们为了查询方便,把学生表和卡表这样做:
但是当我们再次重构数据库的时候,我们就要根据三范式来判断下了。例如,卡内金额依赖于主键学号和卡号,而卡内金额也依赖于卡号,这里就不满足2NF了,我们就要将两张表拆开。
三,3NF
定义:
R满足1NF,且每个非主属性都不传递依赖R的候选键,则称实体E时第三范式。
什么是非主属性传递码?
如图所示,为传递函数依赖的示意图:
例如,
还是上面那张表,我们在这里选的是学号作为主键,则表中有:
学号→卡号→卡内金额,此时出现了传递依赖。
分析:
2NF和3NF,无论是出现部分依赖还是出现传递依赖,都是要将关系模式进行分解,追究产生错误的根源,感觉还是E-R图没有画好的缘故。
小结:
1NF将属性拆成了原子值;2NF和3NF都是为了消除冗余和异常问题;
所以,三范式有两个作用:一是可以衡量一个数据库的好坏;二是可以作为数据库设计的一个基本原则。
三大范式并不是用来区别的,是关系型数据库里的规范,是为了减少数据冗余。如果三个规范都满足说明的你的数据库比较健全,数据冗余少,后期维护也方便。用多了就知道了。如果一定要记下,记住定义就好。第一范式:确保每列的原子性.
如果每列(或者每个属性)都是不可再分的最小数据单元(也称为最小的原子单元),则满足第一范式.
例如:顾客表(姓名、编号、地址、……)其中"地址"列还可以细分为国家、省、市、区等。
第二范式:在第一范式的基础上更进一层,目标是确保表中的每列都和主键相关.
如果一个关系满足第一范式,并且除了主键以外的其它列,都依赖于该主键,则满足第二范式.
例如:订单表(订单编号、产品编号、定购日期、价格、……),"订单编号"为主键,"产品编号"和主键列没有直接的关系,即"产品编号"列不依赖于主键列,应删除该列。
第三范式:在第二范式的基础上更进一层,目标是确保每列都和主键列直接相关,而不是间接相关.
如果一个关系满足第二范式,并且除了主键以外的其它列都不依赖于主键列,则满足第三范式.
为了理解第三范式,需要根据Armstrong公里之一定义传递依赖。假设A、B和C是关系R的三个属性,如果A-〉B且B-〉C,则从这些函数依赖中,可以得出A-〉C,如上所述,依赖A-〉C是传递依赖。
通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解):
第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;
第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;
第三范式:3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。
没有冗余的数据库设计可以做到。但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。具体做法是: 在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余。