目录
关系型数据库的范式
一,第一范式
1,描述
2,例子
二,第二范式
1,描述
2,例子
三,第三范式
1,描述
2,例子
四,BCNF范式
1,描述
2,例子
五,第四范式
1,描述
2,例子
六,第五范式
1,描述
2,例子
七,完全函数依赖
1,描述
2,例子
八,总结
范式是关系型数据库的设计标准,范式分别有第一范式,第二范式,第三范式,BCNF范式(是在第三范式的补充和修订),第四范式和第五范式,
数据库表中的字段都是单一属性的,不可再分。这个单一属性可以是数据库中任何一种基本数据类型。如整型,字符型,日期型等。只要是关系型数据库都会满足第一范式。
例如:一个产品信息表,描述产品信息的字段有产品编号,产品名称,产品数量,产品价格,产品描述。
字段名 |
数据类型 |
产品编号 |
整型 |
产品名称 |
字符型 |
产品数量 |
整型 |
产品价格 |
实型 |
产品描述 |
字符型 |
第二范式是在第一范式的基础上进一步对关系型数据库进行规范,数据库表汇总不存在非关键字段对任一后选关键字段的部分函数依赖。意思就是说在第二范式中组合主键(AB)里面的A或B与其他字段不能存在组合重复。常用的做法是单加一个逐渐ID列,不使用组合主键。
如果不按照第二范式要求设计表,就会出现以下4个问题:
1)数据冗余
同一个产品由N个顾客购买,“产品类型”就重复N-1次;通一个顾客购买了多件产品,那么久会多次记录顾客的个人信息。
2)更新异常
若调整某个产品类型。数据表中所有行的“产品类型”值都要更新,否则会出现同一种产品不同类型的情况。
3)插入异常
假设新进一个产品,暂时还没有人购买。这样,由于没有人购买,产品的名称和类型也无法记录到数据库中。
4)删除异常
假设一批顾客把已经购买完的产品退货,这些产品信息就从数据库表中删除了。但是与此同时,产品名称和产品类型等信息也被删除了,这就导致了删除异常。
为了消除数据冗余,更新异常,插入异常和删除异常,可以把现有的表拆分为3张表:
购物信息表(客户编号,产品名称,产品数量,产品类型,产品价格,客户类型)
客户编号 |
客户类型 |
产品名称 |
产品数量 |
产品类型 |
产品价格 |
客户1 |
会员 |
产品1 |
1 |
零食 |
11 |
客户1 |
会员 |
产品2 |
2 |
粮油 |
12 |
客户1 |
会员 |
产品3 |
3 |
水果 |
13 |
客户2 |
非会员 |
产品1 |
1 |
零食 |
11 |
客户2 |
非会员 |
产品2 |
2 |
粮油 |
12 |
客户2 |
非会员 |
产品3 |
3 |
水果 |
13 |
把购物信息表分解为三个表:
产品类型表(产品类型,产品名称)
客户信息表(客户编号,客户类型)
产品信息表(产品名称,产品类型,产品价格,产品数量)
产品类型表:产品类型,产品名称。
产品类型 |
产品名称 |
零食 |
产品1 |
粮油 |
产品2 |
水果 |
产品3 |
客户信息表:客户编号,客户类型。
客户编号 |
客户类型 |
客户1 |
会员 |
客户2 |
非会员 |
产品信息表:产品名称,产品类型,产品价格,产品数量。
产品名称 |
产品类型 |
产品价格 |
产品数量 |
产品1 |
零食 |
11 |
1 |
产品2 |
粮油 |
12 |
2 |
产品3 |
水果 |
13 |
3 |
第三范式是在第二范式的基础上对数据库设计进行规范,要求是数据表中不存在非关键字段对任一后选关键字段的传递函数依赖。所谓传递函数依赖,指的是如果存在A决定B,B决定C的决定关系,则C传递函数依赖于A。
因此,满足第三范式的数据库表应该不存在依赖关系,假定员工信息表(员工编号,姓名,年龄,所在部门,部门电话),使用员工编号作为管用信息的主键,那么久存在决定关系,员工编号就决定了姓名,年龄,所在部门,部门电话这些字段。
员工信息表(员工编号,姓名,年龄,所在部门,部门电话)
员工编号 |
姓名 |
年龄 |
所在部门 |
部门电话 |
员工1 |
员工1 |
1 |
部门1 |
电话1 |
员工2 |
员工2 |
2 |
部门2 |
电话2 |
从上面关系可以看出,在表中有一个主键,数据表的设计符合第二范式,但不符合第三范式的要求,因为存在决定关系;员工编号就决定了所在部门,所在部门又决定了所在部门的电话;那么久存在了传递函数依赖关系,即员工编号决定部门电话,那么也会出现不满足第二范式时的数据冗余和更新,插入,删除异常的情况,为了满足第三范式的要求,必须把员工信息表插入分成如下两个数据表;
员工表(员工编号,姓名,年龄,所在部门)
员工编号 |
姓名 |
年龄 |
所在部门 |
员工1 |
员工1 |
1 |
部门1 |
员工2 |
员工2 |
2 |
部门2 |
部门表(部门名称,部门电话)
部门名称 |
部门电话 |
部门1 |
电话1 |
部门2 |
电话2 |
除了上面三种范式以外,还有一种经常使用的鲍依斯-科得范式(BCNF)。
它说明,建立在第三范式的基础上,如果数据库表中不存在任何字段对任一后选关键字点的传递函数依赖,那么就符合BCNF范式,BCNF的条件有:
1)所有非主属性对每一个候选键都是完全函数依赖;
2)所有主属性对每一个不包含它的候选键,也是完全函数依赖;
3)没有任何属性完全函数依赖于非候选键的任何一组属性。
解决第三范式的问题:数据冗余度大;插入操作复杂;删除操作复杂;修改操作复杂。
假设仓库管理关系表(仓库ID,存储物品ID,管理员ID,数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品。这个数据库表中存在如下决定关系:
(仓库ID,存储物品ID)→(管理员ID,数量) (管理员ID,存储物品ID)→(仓库ID,数量)
所以,(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是仓库管理关系表的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID)→(管理员ID) (管理员ID)→(仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合BCNF范式。
仓库管理关系表(仓库ID,存储物品ID,管理员ID,数量)
仓库ID |
存储物品ID |
管理员ID |
数量 |
仓库A |
物品A |
管理员A |
1 |
仓库A |
物品B |
管理员A |
2 |
仓库B |
物品A |
管理员B |
1 |
仓库B |
物品B |
管理员B |
2 |
把仓库管理关系表分解为二个关系表:
仓库管理表:(仓库ID,管理员ID);
仓库表:(仓库ID,存储物品ID,数量)。
仓库管理表:(仓库ID,管理员ID);
仓库ID |
管理员ID |
仓库A |
管理员A |
仓库B |
管理员B |
仓库表:(仓库ID,存储物品ID,数量)。
仓库ID |
存储物品ID |
数量 |
仓库A |
物品A |
1 |
仓库A |
物品B |
2 |
仓库B |
物品A |
1 |
仓库B |
物品B |
2 |
设关系R(X,Y,Z),其中X,Y,Z是成对的、不相交属性的集合。
符合第三范式和BCNF之后,消去其中不是函数依赖的非平多值依赖。就是多对多
一个用户有多个表空间,多个表
用户资源表1(用户名,表空间,表名称)
用户名 |
表空间 |
表名称 |
Sys |
tablespace1 |
table1 |
Sys |
tablespace1 |
table2 |
用户资源表2(用户名,名称,种类)
用户名 |
名称 |
种类 |
Sys |
table1 |
table |
Sys |
table1 |
table |
Sys |
tablespace1 |
tablespace |
Sys |
tablespace1 |
tablespace |
消除了第四范式中的连接依赖。
我们在上述例子上进行修改,分成表空间的表和用户拥有表的表,我们可以回想一下,oracle貌似就是这么做的。
表空间的表(用户名,表空间)
用户名 |
表空间 |
Sys |
tablespace1 |
Sys |
tablespace2 |
用户拥有表(用户名,表名称)
用户名 |
表名称 |
Sys |
table1 |
Sys |
table2 |
完全函数依赖:在一个关系中,若某个非主属性数据项依赖于全部关键字称之为完全函数依赖。如果非主属性B函数依赖于构成某个候选关键字的一组主属性A,而且A的任何一个真子集不能被B函数依赖,则称B完全函数依赖于A;反之,若B函数能依赖于A的真子集,则称B部分函数依赖于A。
成绩表(学号,课程号,成绩)关系中,
完全函数依赖:(学号,课程号)→ 成绩,学号 -\→ 成绩,课程号 -\→ 成绩,所以(学号,课程号)→ 成绩 是完全函数依赖
不能说规范化程度越高的关系模式就越好,在设计数据库模式结构时,必须对现实世界的实际情况和用户需求做进一步分析,确定一个合适的、能够反映现实世界的模式。范式就是在数据库表设计时移除数据冗余的过程。随着范式级别的提升,数据冗余越来越少,但数据库的效率也越来越低。一般情况下,数据库设计满足第三范式即可。上面的规范化步骤可以在其中任何一步终止。规范化的过程可概括如下:
(1)取原始的1NF关系投影,消去非主属性对键的部门函数依赖,从而产生一组2NF关系。
(2)取2NF关系的投影,消去非主属性对键的传递函数依赖,产生一组3NF关系。
(3)取这些3NF的投影,消去决定因素不是键的函数依赖。产生一组BCNF关系。
(4)取这些BCNF关系的投影,消去其中不是函数依赖的非平多值依赖,产生一组4NF关系。
(5)取这些4NF的投影,消除了4NF中的连接依赖,产生一组5NF关系。