转:关系数据库中关系模式的规范过程
转载自http://www.gotoread.com/mag/10343/contribution144381.html
一、引言
一个不好的关系模式存在插入异常、删除异常、更新异常和数据冗余。这些异常都是由不好的数据依赖造成的。而规范化理论正是用 来改造关系模式,通过分解关系模式来消除其中不合适的数据依赖,以解决插入异常、删除异常、更新异常和数据冗余问题。规范化过程是围绕范式而进行的。一个 关系型数据库中所有的关系,都应满足一定的要求,我们称为范式。根据满足不同程度的要求,把范式分为多种:满足最低要求的一级叫做一范式(1NF),在一 范式的基础上提出了二范式(2NF),在二范式的基础上又提出了三范式(3NF),以后又提出了BCNF范式,4NF,5NF。范式的等级越高,应满足的 约束条件也就越严格。规范的每一级别都依赖于它的前一级别,反之不成立。例如若一个关系模式满足2NF,则一定满足1NF。但若一个关系模式满足1NF, 则不一定满足2NF。
是否规范化的程度越高越好?这要根据需要来决定,因为“分离”越深,产生的关系越多。关系过多,连接操作越频繁,而连 接操作是最费时间的,特别对以查询为主的数据库应用来说,频繁的连接会影响查询速度。一般情况下,拆分到3NF是一个比较好的中间点。下面按照范式级别依 次介绍1NF、2NF和3NF。
二、一范式(1NF)的规范化过程
一范式(1NF):在数据库表中,每个属性都是不可再分的 数据项,则该关系属于一范式。也就是说不允许表中含表的情况。第一范式是对关系模式的最起码的要求。不满足第一范式的数据库模式不能称为关系数据库。但是 满足第一范式的关系模式并不一定是一个好的关系模式。
例如:关系学生课程表SC(Sno,Cno),其中Sno为学号,Cno为课程号。这 样的关系模式在实际应用过程中会存在这样问题,一个学生可以同时选择多门课程,现将该关系中Sno作为码,Cno字段中存在了多个与之对应的值的情况,如 下表所示:
Sno Cno
Cno1 Cno2 Cno3
20100001 C1 C2 C3
20100002 C1 C3 C6
这样的关系不满足第一范式的要求。因为Cno中有多个数据项。在实际应用中,设计的表,都应该满足第一范式。应改为如下 表所示:
Sno Cno
20100001 C1
20100001 C2
20100001 C3
20100002 C1
20100002 C3
20100002 C6
三、二范式(2NF)的规范化过程
二范式 (2NF):如果某关系满足一范式,并且它的所有非主属性都完全函数依赖于码,则该关系满足二范式。也就是在一范式的基础上消除了非主属性对码的部分函数 依赖。在判定是否为二范式时,一旦发现有一个非主属性部分函数依赖于码,则判定它不属于二范式。
例如:关系模式 SLC(Sno, Sdept, Sloc, Cno, Score),其中Sno为学号、Sdept为系别、Sloc为学生住处,并且每个系的学生住在同一个地方。Cno为课程号、Score为学生成绩。其中 每个学生可以选修多门课程,一门课程可以被多个学生选修。一个学生选定一门课程后就会产生一个成绩。根据语义,码为属性组合(Sno、Cno)。函数依赖 图如下:
图中用虚线表示部分函数依赖。可以看到非主属性 Sdept、Sloc部分函数依赖于码。所以SLC∈2NF。
在应用中使用这个关系模式可能存在以下问题:
1. 插入异常。 假设来了个新生还未选课,即Cno为空。如Sno=95102,Sdept=IS,Sloc=N。因课程号是主属性,根据实体完整性,主属性不能为空或部 分为空,所以该学生的信息无法插入SLC。另外,如果成立了一个新系还没有招生,即Sno、Cno都为空。根据实体完整性,该系的信息也无法插入。
2. 删除异常。假定某个学生本来只选修了3号课程这一门课。现在因身体不适,他连3号课程也不选修了。因课程号是主属性,此操作将导致该学生信息的整个元组都 要删除。另外,如果一个系的学生都毕业走了,在删除学生信息的同时该系的信息也将被删除。
3. 修改复杂。
例如学生转系,在修改此学生元组的Sdept值的同时,还可能需要修改住处(Sloc)。如果这个学生选修了K门课,则必须无遗漏地修改K个元组中全部 Sdept、Sloc信息。在如系之间调整住处(Sloc),假设一个系有1000个人,每个人平均选修了10门课,住处(Sloc)需无遗漏地修改1万 次。
4. 数据冗余度大
假设一个系有1000个人,每个人平均选修了10门课,住处(Sloc)需重复存放1万次。再如一个学生选修了10门课程,那么他的Sdept和Sloc 值就要重复存储了10次。
分析原因:非主属性Sdept、Sloc仅依赖于Sno这个字段,也就是Sdept、Sloc部分函数依赖于码 (Sno,Cno)而不是完全函数依赖。
解决思路:消除了非主属性对码的部分函数依赖。
解决方法:用投影分解将关系模式 SLC进行分解。具体步骤如下:
把部分函数依赖于码的属性取出来;对SLC而言,取出属性Sdept、Sloc。
把剩下的属 性构成一个独立的关系模式;对SLC而言,将剩下的属性Sno, Cno, Score构成一个独立的关系模式。即SC(Sno, Cno, Score)。
找出取出属性的决定因素并将它们放在一起构成一个独立的关系模式;对SLC而言,找出取出属性Sdept、Sloc的决定因 素Sno并将它们放在一起构成一个独立的关系模式。即SL(Sno、Sdept、Sloc)。
综上所述,原关系模式SLC(Sno, Sdept, Sloc, Cno, Score)分解为两个关系模式:SC(Sno, Cno, Score)和SL(Sno、Sdept、Sloc)。
四、三范式(3NF)的规范化过程
三范式(3NF):如果某关系模式 满足第二范式,并且它的任何一个非主属性都不传递依赖于码,则满足第三范式。
例如:上述例子中的关系模式SC(Sno, Cno, Score)。根据语义,码为属性组合(Sno、Cno)。函数依赖图如下:
由图可知,码 (Sno、Cno)函数确定非主属性Score,不存在非主属性对码的传递函数依赖,满足3NF。
再如:上述例子中的关系模式 SL(Sno、Sdept、Sloc)。根据语义,码为属性Sno。函数依赖图如下:
由图可 知,码Sno函数确定非主属性Sdept,Sdept函数确定非主属性Sloc。Sloc传递函数依赖于Sno,即SL中存在非主属性对码的传递函数依 赖。
在应用中使用这两个关系模式可能存在以下问题:
1. 插入异常。 如果成立了一个新系还没有招生,即Sno为空。根据实体完整性,该系的信息也无法插入。但假设来了个新生还未选课,即Cno为空。如 Sno=95102,Sdept=IS,Sloc=N。因学号非空,我们可以将该学生的信息插入SL中。
2. 删除异常。如果一个系的学生都毕业走了,在删除学生信息的同时该系的信息也将被删除。但假定某个学生本来只选修了一门课。现在因身体不适,他连一门课程也 不选修了。在删除该学生选课情况时,学生的信息不会丢失。因为学生的学号非空,所以学生信息还在SL中。
3. 修改复杂。
例如系之间调整住处(Sloc),假设一个系有1000个人,每个人平均选修了10门课,住处(Sloc)需无遗漏地修改1000次。但学生转系,不管一 个学生选修了多少门课,都只需要在SL中修改1个元组的Sdept、Sloc信息。
4. 数据冗余度大
假设一个系有1000个人,每个人平均选修了10门课,住处(Sloc)需重复存放1000次。但不管一个学生选修了多少门课,都只需要在SL中存放1个 元组的Sdept、Sloc信息。
分解之后的两个关系模式SC和SL和原关系模式SLC相比:在一定程度上减轻原F关系模式SLC中存在的 插入异常、删除异常、数据冗余度大、修改复杂等问题。但并不能完全消除关系模式中的各种异常情况和数据冗余。
分析原因:非主属性Sloc传 递依赖于码Sno。
解决思路:消除了非主属性对码的传递函数依赖。
解决方法:用投影分解法将关系模式SL进行分解。具体步骤 如下:
把传递函数依赖于码的属性取出来;对SL而言,取出属性Sloc。
把剩下的属性构成一个独立的关系模式;对SL而言, 将剩下的属性Sno, Sdept构成一个独立的关系模式。即SD(Sno, Sdept)。
找出取出属性的决定因素并将它们放在一起构成 一个独立的关系模式;对SL而言,找出取出属性Sloc的决定因素Sdept并将它们放在一起构成一个独立的关系模式。即DL(Sdept、Sloc)。
综 上所述,关系模式SL (Sno, Sdept, Sloc)分解为两个关系模式:SD(Sno, Sdept)和DL(Sdept、Sloc)。
所 以,原模式SLC(Sno, Sdept, Sloc, Cno, Score)按如下分解满足3NF:
SC(Sno, Cno, Score),SD(Sno, Sdept),DL(Sdept、Sloc)
在应用中使用这三个关系模式不会存在以下问题:
1. 插入不异常。 如果成立了一个新系还没有招生,因为系Sdept非空,该系的信息可以插入DL中。假设来了个新生还未选课,因学号非空,我们可以将该学生的信息插入SD 中。
2. 删除不异常。如果一个系的学生都毕业走了,在删除学生信息的同时该系的信息不会被删除。因为系的系号非空,所以系信息还在DL中。又如某个学生本来只选修 了一门课。现在因身体不适,他连一门课程也不选修了。在删除该学生选课情况时,学生的信息不会丢失。因为学生的学号非空,所以学生信息还在SD中。
3. 修改不复杂。
例如系之间调整住处(Sloc),不管一个系有多少个学生,住处(Sloc)只需在DL中修改1次。又如学生转系,不管一个 学生选修了多少门课,都只需要在SD中修改1个元组的Sdept信息。
4. 数据冗余度不大
不管一个系有多少个学生,住处 (Sloc)只需在DL中存放1次。但系(Sdept)还得多次存放。冗余只能尽可能减少,不能避免。因为如果没有冗余,数据间就没了联系。
五、 结束语
本文分析了1NF、2NF、3NF。但是3NF只限制了非主属性对码的依赖关系,没有限制主属性对码的依赖关系。如果存在主属性对码 的依赖关系,仍会产生插入异常、删除异常、数据冗余度大、修改复杂等问题。在此我们不作讨论,有兴趣的读者可参阅有关文献。