数据库六种范式详解(1NF/2NF/3NF/BCNF/4NF/5NF)

目录

数据库的基本概念

函数依赖

函数依赖的定义

函数依赖与属性的关系

六种范式

第一范式(1NF)

第二范式(2NF)

第三范式(3NF)

巴斯-科德范式(BCNF,Boyce-Codd Normal Form)

第四范式(4NF)

第五范式(5NF)

范式规范化路线

范式规范化实例


数据库的基本概念

范式:
设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式。
各种范式呈递次规范,越高的范式数据库冗余越小。有冗余的数据库未必是最好的数据库, 有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF)。一般说来,数据库只需满足第三范式(3NF)就行了。
满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一个数据库设计如果符合第二范式,一定也符合第一范式。如果符合第三范式,一定也符合第二范式。
实体:
在数据库中往往是一个数据表。
属性:
在关系数据库中,属性可以看作是“表的一列”。
元组:
表中的一行就是一个元组。
分量:
即元组的某个属性值。在一个关系数据库中,属性是一个操作原子,即关系数据库在做任何操作的时候,属性是“不可分的”。否则就不是关系数据库了。
候选码和主码:
表中可以唯一确定一个元组的某个属性(或者属性组)叫候选码,我们从许多个候选码中挑一个就叫主码。
全码:
如果一个码包含了所有的属性,这个码就是全码。
主属性:
一个属性只要在任何一个候选码中出现过,这个属性就是主属性。
非主属性:
与上面相反,没有在任何候选码中出现过,这个属性就是非主属性。
外码:
一个属性(或属性组),它不是码,但是它别的表的码,它就是外码。

函数依赖

函数依赖的定义

设R(U)是一个属性集U上的一个关系模式,X和Y是U的子集。若对于R(U)的任意两个可能的具体关系r1、r2,若r1[x]等于r2[x]则r1[y]等于r2[y],或者若r1[x] != r2[x]则r1[y] != r2[y],称X决定Y,或者Y函数依赖于X,记作X→Y。即像函数一样,给一个确定的输入(属性集X),有一个确定的输出(属性集Y)。
抽象的“关系模式”和具体存在的“关系”,下文统称“关系”。下面是几种函数依赖的定义:

  • 如果X→Y,但Y为X的子集, 则称X→Y是平凡函数依赖。
    举例:
    关系R(Sno, Cno),依赖关系(Sno, Cno)→Sno,(Sno, Cno)→Cno都是平凡函数依赖。
  • 如果X→Y,但Y不为X的子集,则称X→Y是非平凡的函数依赖。
    举例:
    关系R(Sno, Cno, Grade),依赖关系(Sno, Cno)→Grade是非平凡函数依赖。
  • 如果X→Y,存在X的真子集X1,使得X1→Y,则称Y部分依赖于X。也就是Y依赖于部分的X。
    举例:
    学生表(学号, 姓名, 性别, 班级, 年龄),(学号, 姓名)→性别,学号→性别,所以(学号, 姓名)→性别是部分函数依赖。
  • 如果X→Y,但任何X的真子集X1都不存在X1→Y则称Y完全依赖于X。
    举例:
    成绩表(学号, 课程号, 成绩),(学号, 课程号)→成绩,学号!→成绩,课程号!→成绩,所以(学号, 课程号)→成绩是完全函数依赖。
  • 如果X→Y,Y→Z,X⊄Y,Y!→X,(X∪Y)∩Z=∅,则称Z传递依赖于X。
    举例:
    关系S(学号, 系名, 系主任),学号→系名,系名→系主任,系名!→学号,所以学号→系主任为传递函数依赖。

函数依赖与属性的关系

设R(U)是属性集U上的关系模式,X、Y是U的子集。

如果X和Y之间是一对一(1:1)关系,如学校和校长,则存在函数依赖X→Y和Y→X。
如果X和Y之间是一对多(1:n)关系,如年龄和姓名,则存在函数依赖Y→X。
如果X和Y之间是多对多(m:n)关系,如学生和课程,则X和Y之间不存在函数依赖。

六种范式

第一范式(1NF)

简单来说就是属性不可分(1NF是对属性的原子性约束,要求属性具有原子性,不可再分解)。数据库表的每一列(也称为属性)都是不可分割的原子数据项,不能是集合,数组,记录等非原子数据项。实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个域值只能是实体的一个属性或一个属性的一部分。简而言之,第一范式就是无重复的域。

第二范式(2NF)

在满足第一范式(1NF)的基础上,每一个非码属性(不在主键中的列)都必须完全函数依赖于候选码。(2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性,更通俗的说法就是一个表必须有主键ID)。

第三范式(3NF)

在满足第二范式(2NF)的基础上,每个非主属性不依赖于其它非主属性(即在2NF基础上,消除非码属性对候选码的传递函数依赖。3NF是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余)。
也就是说,任何非主属性都直接依赖于主属性,不能传递依赖于主属性。即表中的每一列只与主键直接相关,而不是间接相关(表中的每一列只能依赖于主键)。每一个非码属性既不部分依赖于码,也不传递依赖于码。

巴斯-科德范式(BCNF,Boyce-Codd Normal Form)

某些特殊情况下,即使关系模式符合3NF的要求,仍然存在着插入异常,修改异常与删除异常的问题。BCNF由Boyce与Codd提出,通常被认为是修正的第三范式。
巴斯-科德范式即在满足第三范式(3NF)基础上,任何非主属性不能对主键子集依赖(即在3NF基础上,消除主属性对候选码的部分函数依赖和传递函数依赖)。
BC范式既检查非主属性,又检查主属性。当只检查非主属性时,就成了第三范式。满足BC范式的关系都必然满足第三范式。或者还可以换一种说法:若一个关系达到了第三范式,并且它只有一个候选码,或者它的每个候选码都是单属性,则该关系自然达到BC范式。
一般来说,一个数据库设计符合3NF或BCNF就可以了。

第四范式(4NF)

多值依赖的概念:
多值依赖即属性之间的一对多关系,记为K→→A。
函数依赖事实上是单值依赖,所以不能表达属性值之间的一对多关系。
平凡的多值依赖:全集U=K+A,一个K可以对应于多个A,即K→→A。此时整个表就是一组一对多关系。
非平凡的多值依赖:全集U=K+A+B,一个K可以对应于多个A,也可以对应于多个B,A与B互相独立,即K→→A,K→→B。整个表有多组一对多关系,且有:“一”部分是相同的属性集合,“多”部分是互相独立的属性集合。

第四范式即在满足巴斯-科德范式(BCNF)的基础上,消除非平凡且非函数依赖的多值依赖(即把同一表内的多对多关系删除)。

第五范式(5NF)

即在满足第四范式(4NF)的基础上,消除不是由候选码所蕴含的连接依赖。如果关系模式R中的每一个连接依赖均由R的候选码所隐含,则称此关系模式符合第五范式。
函数依赖是多值依赖的一种特殊的情况,而多值依赖实际上是连接依赖的一种特殊情况。但连接依赖不像函数依赖和多值依赖可以由语义直接导出,而是在关系连接运算时才反映出来。存在连接依赖的关系模式仍可能遇到数据冗余及插入、修改、删除异常等问题。

范式规范化路线

第一范式(1NF)
非码的非平凡 | ↓ 消除非主属性对码的部分函数依赖
第二范式(2NF)
↓ 消除非主属性对码的传递函数依赖
第三范式(3NF)
↓ 消除主属性对码的部分和传递函数依赖
BC范式(BCNF)
↓ 消除非平凡且非函数依赖的多值依赖
第四范式(4NF)
↓消除不是由候选码所蕴含的连接依赖
第五范式(5NF)

范式规范化实例

以一个学校的学生系统为例分析说明,这几个范式的应用。首先我们确定一下要设计的内容包括那些。学号、学生姓名、年龄、性别、课程、课程学分、系别、学科成绩,系办地址、系办电话等信息。为了简单我们暂时只考虑这些字段信息。我们对于这些信息,关心的问题有如下几个方面:
学生有那些基本信息;
学生选了那些课,成绩是什么;
每个课的学分是多少;
学生属于那个系,系的基本信息是什么。
第一范式:
满足第一范式(1NF)的数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。在当前的任何关系数据库管理系统( DBMS )中,傻瓜也不可能做出不符合第一范式的数据库,因为这些DBMS不允许你把数据库表的一列再分成二列或多列。因此,你想在现有的DBMS中设计出不符合第一范式的数据库都是不可能的。
第二范式:
首先我们考虑把所有这些信息放到一个表中(学号,学生姓名、年龄、性别、课程、课程学分、系别、学科成绩,系办地址、系办电话 ) ,表中存在如下的依赖关系:

(学号, 课程名称) → (姓名, 年龄, 成绩, 学分)

姓名和年龄不依赖于课程,即不完全依赖于主属性,因此不满足第二范式的要求,会产生如下问题:

  • 数据冗余:同一门课程由n个学生选修, " 学分 " 就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
  • 更新异常:若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况;假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
  • 删除异常 :假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。

解决方案:把选课关系表SelectCourse改为如下三个表:

学生:Student(学号,姓名,年龄,性别,系别,系办地址、系办电话)
课程:Course(课程名称,学分)
选课关系:SelectCourse(学号,课程名称,成绩)

第三范式:

 

接着看上面的学生表Student(学号,姓名,年龄,性别,系别,系办地址、系办电话),关键字为单一关键字"学号",因为存在如下决定关系:

(学号)→ (姓名,年龄,性别,系别,系办地址、系办电话)

但是还存在下面的决定关系:

(学号) → (系别)→(系办地点,系办电话)

即存在非关键字段"系办地点"、"系办电话"对关键字段"学号"的传递函数依赖。它也会存在数据冗余、更新异常、插入异常和删除异常的情况。
解决方案:根据第三范式把学生关系表分为如下两个表就可以满足第三范式:

学生:(学号,姓名,年龄,性别,系别);
系别:(系别,系办地址、系办电话)。

上面的数据库表就是符合1NF、2NF、3NF的数据库,消除了数据冗余、更新异常、插入异常和删除异常。

BC范式:
假设有如下条件:
某公司有若干个仓库;
每个仓库只能有一名管理员,一名管理员只能在一个仓库中工作;
一个仓库中可以存放多种物品,一种物品也可以存放在不同的仓库中。每种物品在每个仓库中都有对应的数量。
那么关系模式仓库(仓库名,管理员,物品名,数量) 属于哪一级范式?
已知:
函数依赖集:仓库名 → 管理员,管理员 → 仓库名,(仓库名,物品名)→ 数量
码:(管理员,物品名),(仓库名,物品名)
主属性:仓库名、管理员、物品名
非主属性:数量

因为不存在非主属性对码的部分函数依赖和传递函数依赖,所以此关系模式属于3NF。

既然此关系模式已经属于3NF,那么这个关系模式是否存在问题呢?
我们来看以下几种操作:

  • 先新增加一个仓库,但尚未存放任何物品,是否可以为该仓库指派管理员?——不可以,因为物品名也是主属性,根据实体完整性的要求,主属性不能为空。
  • 某仓库被清空后,需要删除所有与这个仓库相关的物品存放记录,会带来什么问题?——仓库本身与管理员的信息也被随之删除了。
  • 如果某仓库更换了管理员,会带来什么问题?——这个仓库有几条物品存放记录,就要修改多少次管理员信息。

从这里我们可以得出结论,在某些特殊情况下,即使关系模式符合3NF的要求,仍然存在着插入异常,修改异常与删除异常的问题,仍然不是"好"的设计。造成此问题的原因是存在着主属性对于码的部分函数依赖与传递函数依赖。(在此例中就是存在主属性【仓库名】对于码【(管理员,物品名)】的部分函数依赖。

解决方案:将表拆分成两个表,在3NF的基础上,消除主属性【仓库名】对于码【(管理员,物品名)】的部分与传递函数依赖。

将原来的仓库(仓库名,管理员,物品名,数量)
修改为:
仓库(仓库名,管理员)
库存(仓库名,物品名,数量)

这样,之前的插入异常,修改异常与删除异常的问题就被解决了。

参考文章

https://blog.csdn.net/zgcr654321/article/details/93385986

猜你喜欢

转载自blog.csdn.net/xiaoxiao_su123/article/details/113514395