设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。
过程 | 影响 |
1NF——>2NF | 消除非主属性对码的部分依赖 |
2NF——>3NF | 消除非主属性对码的函数传递依赖 |
3NF——>BCNF | 消除主属性之间的部分函数依赖和传递函数依赖 |
BCNF——>4NF | 消除非平凡且费函数依赖的多值依赖 |
4NF——>5NF | 消除连接依赖 |
函数依赖:若在一张表中,在属性(或属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作X—>Y,即X能唯一确定Y。
完全函数依赖:设X,Y是关系R的两个属性集合,X'是X的真子集,存在X—>Y,但对每一个X'都有X'!—>Y,则称Y完全函数依赖与X,即X子集不能唯一确定Y。
传递函数依赖:设X,Y,Z是关系R中互不相同的属性集合,存在X—>Y(Y!—>X),Y—>Z,则称Z传递函数依赖于X。
平凡函数依赖:当关系中属性集合Y是属性集合X的子集时,存在函数依赖X→Y,即一组属性函数决定它的所有子集,则称X平凡函数依赖于Y。
非平凡函数依赖:当关系中属性集合Y不是属性集合X的子集时,存在函数依赖X→Y,,则称X非平凡函数依赖于Y。
码:属性或属性组K能够唯一确定表中其余所有元素,则K称为码,包含在任意一个码中的属性称为主属性(主码)。
1NF是所有关系型数据库的最基本要求,强调数据表的原子性,每个属性都不可再分。表1所示情况,就不符合1NF要求:
编号 | 品名 | 进货 | 出货 | 备注 | ||
数量 | 单价 | 数量 | 单价 |
而表2形式设计就符合1NF要求:
编号 | 品名 | 进货数 | 销售成本 | 出货数 | 销售售价 | 备注 |
但是仅仅按照1NF设计,会出现大量的数据冗余,以及插入、删除、修改异常等问题,例如表3的设计:
学号 | 姓名 | 系名 | 系主任 | 课名 | 分数 |
1.每一名学生的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次——数据冗余过大
2.假如学校新建了一个系,但是暂时还没有招收任何学生,那么无法将系名与系主任的数据单独地添加到数据表中——插入异常
3.假如将某个系中所有学生相关的记录都删除,那么所有系与系主任的数据也就随之消失了,但一个系所有学生都没有了,并不表示这个系就没有了——删除异常
4.假如某同学转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据——修改异常
2NF在1NF的基础上,消除了非主属性对于码的部分函数依赖,换句话说,数据表中的所有非主属性都要和该数据表的逐渐有完全依赖关系。判断设计是否满足第二范式:
第一步:找出数据表中所有的码。
第二步:根据第一步所得到的码,找出所有的主属性。
第三步:数据表中,除去所有的主属性,剩下的就都是非主属性了。
第四步:查看是否存在非主属性对码的部分函数依赖。
则表3中所有的关系依赖如图1所示:
为了让设计符合2NF的要求,必须消除这些部分函数依赖,只有一个办法,就是将大数据表拆分成两个或者更多个更小的数据表,在拆分的过程中,要达到更高一级范式的要求,这个过程叫做”模式分解“,但模式分解的方法不是唯一的。其中一种如图2所示:
3NF在2NF的基础之上,要求表中的所有数据元素不但要能唯一地被主关键字所标识,而且它们之间还必须相互独立,不存在其他的函数关系。消除非主属性对于码的传递函数依赖。
对于其中学生表,主码为学号,主属性为学号,非主属性为姓名、系名和系主任。因为 学号 → 系名,同时 系名 → 系主任,所以存在非主属性系主任对于码学号的传递函数依赖,所以学生表的设计,不符合3NF的要求,得到新的表结构划分如图3所示:
在第三范式的基础上近一步消除主属性对于码的部分函数依赖和传递依赖,BCNF不仅需要符号3NF,而且主属性还不依赖与主属性。
若:1)某公司有若干个仓库;2)每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作;3)一个仓库中可以存放多种物品,一种物品也可以存放在不同的仓库中。每种物品在每个仓库中都有对应的数量。
决定关系:(仓库ID,存储物品ID) →(管理员ID,数量),(管理员ID,存储物品ID) → (仓库ID,数量)
所以,(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是该表的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:(仓库ID) → (管理员ID),(管理员ID) → (仓库ID),即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。
在第三范式基础上,当一个表中的非主属性互相独立时(3NF),这些非主属性不应该有多值。若有多值就违反了第四范式。
有这样一个用户联系方式表TELEPHONE(CUSTOMERID,PHONE,CELL)。CUSTOMERID为用户ID,PHONE为用户的固定电话,CELL为用户的移动电话。本来,这是一个非常简单的第3范式表。主键为CUSTOMERID,不存在传递依赖。但在某些情况下,这样的表还是不合理的。比如说,用户有两个固定电话,两个移动电话。这时,表的具体表示如下:
CUSTOMERID PHONE CELL
1000 8828-1234 149088888888
1000 8838-1234 149099999999
由于PHONE和CELL是互相独立的,而有些用户又有两个和多个值。这时此表就违反第四范式。