3.3 数据库关系模式的规范化
关系数据库的设计主要是关系模式的设计,关系模式设计的好坏将直接影响到数据库设计的成败。
设计数据库时要考虑减少冗余数据和避免数据经常发生变化,减少额外的维护。因为冗余的数据需要额外的维护,避免导致“数据不一致”“插入异常”及“删除异常”等问题的发生。
规范化的核心思想就是表中每个决定因子都必须是候选键;若不满足,可以将表分解成两个或多个满足条件的表。因此,规范化就是检查并修改表使其结构良好的过程,即表中每个决定因子都必须是候选键。这个过程之所以叫规范化,是因为表中容易出现的问题可以归入不同的范式(NormalForm)类型。
将关系模式规范化,使之达到较高的范式是设计好关系模式的唯一途径,否则,设计的关系数据库会产生一系列的问题。
3.3.1 问题的提出
首先回顾一下关系模型的形式化定义。
关系模式的完整表示是一个五元组:R(U,D,Dom,F)
其中,
R:关系名,代表一个关系模式。
U:关系模式R的属性集合(属性组)。
D:属性集合U的数据域。
Dom:属性到域的映射关系。
F:属性集合U上的一组数据依赖的集合。
由于D和Dom对设计关系模式的作用不大,在讨论关系规范化理论时可以把它们简化为三元组:R(U,F)。
从上式可以看出,数据依赖是关系模式的重要因素。
下面以一个实例说明如果一个关系没有经过规范化可能会出现的问题。
例如,要设计一个教学管理数据库,希望从该数据库中得到学生学号、姓名、年龄、性别、系别、系主任姓名、学生学习的课程名和该课程的成绩信息。若将此信息要求设计为一个关系,则关系模式为
S(sno,sname,sage,ssex,sdept,mname,cno,cname,score)
该关系模式中各属性之间的关系如下:
一个系有若干个学生,但一个学生只属于一个系。
一个系只能有一名系主任,但一个系主任可以同时兼几个系的系主任。
一个学生可以选修多门课程,每门课程可被若干个学生选修。
每个学生学习的每门课程都有一个成绩。
可以看出,此关系模式的码为(sno,cno)。仅从关系模式上看,该关系模式已经包括了需要的信息,如果按此关系模式建立关系,并对它进行深入分析,就会发现其中的问题。关系模式S的实例如表3-13所示。
表3-13 关系模式S的实例
从表3-13中的数据情况可以看出,该关系存在以下问题。
1.数据冗余太大
每个系名和系主任的名字存储的次数等于该系学生人数乘以每个学生选修的课程门数,系名和系主任数据重复量太大。
2.插入异常
一个新系没有招生时,或系里有学生但没有选修课程,系名和系主任名无法插入到数据库中。因为在这个关系模式中码是(sno,cno),这时没有学生而使得学号无值,或学生没有选课而使得课程名无值。但在一个关系中,码属性不能为空值,因此,关系数据库无法操作,导致插入异常。
3.删除异常
当某系的学生全部毕业而又没有招新生时,删除学生信息的同时,系及系主任名的信息随之删除,但这个系依然存在,而在数据库中却无法找到该系的信息,即出现了删除异常。
4.更新异常
若某系换系主任,数据库中该系的学生记录应全部修改。如果稍有不慎,某些记录漏改了,则造成数据的不一致,即出现了更新异常。
为什么会发生插入异常和删除异常?原因是该关系模式中属性与属性之间存在不好的数据依赖。一个“好”的关系模式应当不会发生插入和删除异常,冗余度要尽可能地少。
上述异常问题可以看作数据冗余“并发症”,如何检测和消除表3-13所示的学生表中的冗余数据呢?检测和消除数据冗余的最佳方法是数据库规范化。规范化是通过最小化数据冗余来提升数据库质量的过程,它是基于函数依赖以及一系列范式定义的,最为常用的是第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。
对于存在问题的关系模式,可以通过模式分解的方法使之规范化。
例如,将上述关系模式分解成四个关系模式:
S(sno,sname,sage,ssex,sdept)
Course(cno,cname)
SC(sno,cno,score)
DEPT(sdept,mname)
这样分解后,四个关系模式都不会发生插入异常、删除异常的问题,数据的冗余也得到了控制,数据的更新也变得简单。
“分解”是解决冗余的主要方法,也是规范化的一条原则,“关系模式有冗余问题,就分解它”。但是,上述关系模式的分解方案是否就是最佳的?也不是绝对的。如果要查询某位学生所在系的系主任名,就要对两个关系做连接操作,而连接的代价也是很大的。一个关系模式的数据依赖会有哪些不好的性质,如何改造一个模式,这就是规范化理论所讨论的问题。
3.3.2 函数依赖
1.规范化
规范化是指用形式更为简洁、结构更加规范的关系模式取代原有关系模式的过程。关系模式必须满足一定的完整性约束条件以达到现实世界对数据的要求。完整性约束条件主要包括以下两个方面。
1)对属性取值范围的限定。
2)属性值间的相互联系(主要体现在值的相等与否),这种联系称为数据依赖。
2.数据依赖
数据依赖是指通过一个关系中属性间值的相等与否体现出来的数据间的相互关系,是现实世界属性间相互联系的抽象,是数据内在的性质。
数据依赖共有三种:函数依赖(Functional Dependency,FD)、多值依赖(MultiValued De-pendency,MVD)和连接依赖(Join Dependency,JD),其中最重要的是函数依赖和多值依赖。
在数据依赖中,函数依赖是最基本、最重要的一种依赖,它是属性之间的一种联系,假设给定一个属性的值,就可以唯一确定(查找到)另一个属性的值。例如,知道某一学生的学号,可以唯一地查询到其对应的系别,如果这种情况成立,就可以说系别函数依赖于学号。这种唯一性并非指只有一个记录,而是指任何记录。
【定义3.1】设有关系模式R(U),X和Y均为U={A1,A2,…,An}的子集,r是R的任一具体关系,r中不可能存在两个元组在X的属性值相等,而在Y上的属性值不等(也就是说,如果对于r中的任意两个元组t和s,只要有t[X]=s[X],就有t[Y]=s[Y]),则称X函数决定Y,或称Y函数依赖于X,记作X→Y,其中X叫作决定因素(Determinant),Y叫作依赖因素(Dependent)。
在一张表内,两个字段值之间的一一对应关系称为函数依赖。通俗来讲,在一个数据库表内,如果字段A的值能够唯一确定字段B的值,那么字段B函数依赖于字段A。
这里的t[X]表示元组t在属性集X上的值,s[X]表示元组s在属性集X上的值。FD是对关系模式R的一切可能的当前值r的定义,不是针对某个特定关系的。通俗地说,在当前值r的两个不同元组中,如果X值相同,就一定要求Y值也相同,或者说,对于X的每个具体值,都有Y唯一的具体值与之对应。
下面介绍一些相关的术语与记号。
1)X→Y,但,则称X→Y是非平凡的函数依赖。
2)X→Y,但Y⊆X,则称X→Y是平凡的函数依赖。因为平凡的函数依赖总是成立的,所以,若不特别声明,本书后面提到的函数依赖,都不包含平凡的函数依赖。
3)若X→Y,Y→X,则称X↔Y。
4)若Y不函数依赖于X,则记作X→Y。
【定义3.2】在关系模式R(U)中,如果X→Y,并且对于X的任何一个真子集X′,都有,则称Y对X完全函数依赖,记作:
若X→Y,如果存在X的某一真子集X′(X′⊆X),使X′→Y,则称Y对X部分函数依赖,记作:
【定义3.3】在关系模式R(U)中,X、Y、Z是R的3个不同的属性或属性组,如果X→Y(Y⊄X,Y不是X的子集),且,Y→Z,.则称Z对X传递函数依赖,记作:
传递依赖:假设A、B、C分别是同一个数据结构R中的三个元素或分别是R中若干个数据元素的集合,如果C依赖B,而B依赖于A,那么C自然依赖于A,即称C传递依赖A。
加上条件,是因为如果Y→X,则X↔Y,实际上是X→Z,是直接函数依赖而不是传递函数依赖。
【例3-10】设有关系模式S(sno,sname,sage,ssex,sdept,mname,cname,score),判断以下函数依赖的对错。
1)sno→sname,sno→ssex,(sno,cname)→score。
2)cname→sno,sdept→cname,sno→cname。
在1)中,sno和sname之间存在一对一或一对多的联系,sno和ssex、(sno,cname)和score之间存在一对多联系,所以这些函数依赖是存在的。在2)中,因为sno和cname、sdept和cname之间都是多对多联系,因此,它们之间是不存在函数依赖的。
【例3-11】设有关系模式:学生课程(学号,姓名,课程号,课程名称,成绩,教师,教师年龄),在该关系模式中,成绩要由学号和课程号共同确定,教师决定教师年龄。所以,此关系模式中包含了以下函数依赖关系:
学号→姓名(每个学号只能有一个学生姓名与之对应),
课程号→课程名称(每个课程号只能对应一个课程名称),
(学号,课程号)→成绩(每个学生学习一门课只能有一个成绩),
教师→教师年龄(每一个教师只能有一个年龄)。
注意:属性间的函数依赖不是指关系模式R的某个或某些关系满足上述限定条件,而是指R的一切关系都要满足定义中的限定。只要有一个具体关系r违反了定义中的条件,就破坏了函数依赖,使函数依赖不成立。
识别函数依赖是理解数据语义的一个组成部分,依赖是关于现实世界的断言,它不能被证明,决定关系模式中函数依赖的唯一方法是仔细考察属性的含义。
3.码
码是关系模式中的一个重要概念。下面用函数依赖的概念对码做出较为精确的形式化的定义。
【定义3.4】设K是关系模式R(U,F)中的属性或属性集合,K′是K的任一真子集。
若K→U,而不存在K′→U,则K为R的候选码(Candidate Key),简称码。
1)若候选码多于一个,则选取其中的一个为主码(Primary Key)。
2)包含在任一候选码中的属性,称为主属性(Prime Attribute)或码属性。
3)不包含在任何候选码中的属性称为非主属性(Nonprime Attribute)或非码属性(Non-key Attribute)。
4)在关系模式中,最简单的情况,单个属性是码,称为单码(Single Key);最极端的情况,整个属性集合是码,称为全码(All-Key)。
例如,在关系模式S(sno,sdept,sage)中,sno是单码,而在关系模式SC(sno,cno,score)中,属性组合(sno,cno)是码,但在关系模式“签约(演员名,制片公司名,电影名)”中,由于一个制片公司可以为一部电影和多个演员签约,一个演员可以和多个制片公司签约饰演多部电影中的角色,一部电影可由不同的制片公司制作,所以,此关系模式的码为(演员名,制片公司名,电影名),即为全码。
【定义3.5】关系模式R中属性或属性组X并非R的码,但X是另一个关系模式的码,则称X是R的外部码(Foreign key),也称外码。
主码又和外部码一起提供了表示关系间联系的手段。如在SC(sno,cno,score)中,sno不是码,但sno是关系模式S(sno,sdept,sage)的码,则sno是关系模式SC的外码。
3.3.3 范式以及应用案例
当一个关系中存在还可以再分的数据项时,这个关系就是非规范化的关系。非规范化的关系存在两种情况:第一种是关系中具有组合数据项;第二种是关系中具有多值数据项。实例如表3-14和表3-15。
表3-14 具有组合数据项的非规范化关系
表3-15 具有多值数据项的非规范化关系
当一个关系中的所有分量都是不可再分的数据项时,该关系是规范化的,即当关系中不存在组合数据项和多值数据项,只存在不可分的数据项时,这个关系是规范化的。
利用规范化理论,使关系模式的函数依赖集满足特定的要求,满足特定要求的关系模式称为范式。
关系按其规范化程度从低到高可分为5级范式(Normal Form),分别称为1NF、2NF、3NF(BCNF)、4NF、5NF。规范化程度较高者必是较低者的子集,即
5NF⊆4NF⊆BCNF⊆3NF⊆2NF⊆1NF
一个低一级范式的关系模式,通过模式分解可以转换成若干个高一级范式的关系模式的集合,这个过程称为规范化。
规范化的过程如下:
1)标识表中的所有的候选键。
2)标识表中的所有函数依赖。
3)检查函数依赖的决定因子。如果某决定因子不是候选键,则表的结构就有问题。可以通过如下方式实现:
①把函数依赖的列放在它自己的新表中。
②把函数依赖的决定因子作为新表的主键。
③将决定因子的副本作为原表中外键。
④在新表和原表之间创建参照完整性约束。
4)根据需要,多次重复步骤3),直至每个表的决定因子都是候选键。
下面将在函数依赖的范畴内讨论范式问题。
1.1NF
如果一个关系模式R的所有属性都是不可分的基本数据项,则R∈1NF。
第一范式是对关系模式的最起码的要求。不满足第一范式的数据库模式不能称为关系数据库。但是满足第一范式的关系模式并不一定是一个好的关系模式。1NF仍然会出现插入异常、删除异常、更新异常及数据冗余等问题,只有对关系模式继续规范化,使之满足更高的范式,才能得到高性能的关系模式。对表3-14和表3-15分别进行横向和纵向展开,可分别转化为表3-16和表3-17中的符合1NF的关系。
表3-16 消除组合数据项的规范化关系
表3-17 消除多值数据项的规范化关系
2.2NF
【定义3.6】如果关系模式R(U,F)∈1NF,且R中的每个非主属性完全函数依赖于R的某个候选码,则R满足第二范式(Second Normal Form),记作R∈2NF。
【例3-12】关系模式S-L-C(U,F),U={SNO,SDEPT,SLOC,CNO,SCORE},其中,SNO是学号,SDEPT是学生所在系,SLOC是学生的宿舍(住处),CNO是课程号,SCORE是成绩。
该关系模式的码=(SNO,CNO),函数依赖集F={(SNO,CNO)→SCORE,SNO→SDEPT,SNO→SLOC,SDEPT→SLOC},非主属性={SDEPT,SLOC,SCORE},非主属性对码的部分函数依赖={(SNO,CNO)→pSDEPT,(SNO,CNO)→pSLOC}。显然,该关系模式不满足2NF。
不满足2NF的关系模式,会产生以下几个问题:
1)插入异常。插入一个新学生,若该生没有选课,则CNO为空,但码不能为空,所以不能插入。
2)删除异常。某学生只选择了一门课,现在该门课要删除,则该学生的基本信息也将删除。
3)更新异常。某个学生要从一个系转到另一个系,若该学生选修了K门课,必须修改的该学生相关的字段值为2K个(系别、住处),一旦有遗漏,将破坏数据的一致性。
造成以上问题的原因是SDEPT、SLOC部分函数依赖于码。解决的办法是用投影分解把关系模式分解为多个关系模式。投影分解是把非主属性及决定因素分解出来构成新的关系,决定因素在原关系中保持,函数依赖关系相应分开转化(将关系模式中部分依赖的属性去掉,将部分依赖的属性单独组成一个新的模式)。
上述关系模式分解的结果如下:
S-C(SNO,CNO,SCORE)
码={(SNO,CNO)}F={(SNO,CNO)→SCORE}
S-L(SNO,SDEPT,SLOC)
码={SNO}F={SNO→SDEPT,SNO→SLOG,SDEPT→SLOG}
经过模式分解,两个关系模式中的非主属性对码都是完全函数依赖,所以,它们都满足2NF。
3.3NF
【定义3.7】如果关系模式R(U,F)∈2NF,且每个非主属性都不传递函数依赖于任何候选码,则R满足第三范式(Third Normal Form),记作R∈3NF。
在例3-12中,关系S-L(SNO,SDEPT,SLOC),SNO→SDEPT,SDEPT→SLOC,SLOC传递函数依赖于码SNO,所以,S-L不满足3NF。
解决的方法同样是将S-L进行投影分解:
S-D(SNO,SDEPT)码={SNO}F={SNO→SDEPT}
D-L(SDEPT,SLOC)码={SDEPT}F={SDEPT→SLOC}
分解后的关系模式中不再存在传递函数依赖,即关系模式S-D和D-L都满足3NF。3NF是一个可用的关系模式应满足的最低范式,也就是说,一个关系模式如果不满足3NF,则不能使用。
采用投影分解法将一个2NF的关系分解为多个3NF的关系,可以在一定程度上解决原2NF关系中存在的插入异常、删除异常、数据冗余度大、修改复杂等问题。将一个2NF关系分解为多个3NF的关系后,并不能完全消除关系模式中的各种异常情况和数据冗余。
4.BCNF
BCNF(Boyce Codd Normal Form)是由Boyce和Codd提出的,比3NF又进了一步,通常认为BCNF是修正的第三范式,有时也称为扩充的第三范式。
【定义3.8】关系模式R(U,F)∈1NF,若X→Y且Y⊆X时,X必含有码,则R(U,F)∈BCNF。也就是说,关系模式R(U,F)中,若每个决定因素都包含码,则R(U,F)∈BCNF。
由BCNF的定义可以得出结论,一个满足BCNF的关系模式有:
1)所有非主属性对每一个码都是完全函数依赖。
2)所有的主属性对每一个不包含它的码,也是完全函数依赖。
3)没有任何属性完全函数依赖于非码的任何一组属性。
【例3-13】设关系模式SC(U,F),其中,U={SNO,CNO,SCORE},F={(SNO,CNO)→SCORE,(CNO,SCORE)→SNO}。SC的候选码为(SNO,CNO)和(CNO,SCORE),决定因素中都包含码,没有属性对码传递依赖或部分依赖,所以SC∈BCNF。
【例3-14】设关系模式STJ(S,T,J),其中,S:学生,T:教师,J:课程。每位教师只教一门课,每门课有若干教师,某一学生选定某门课,就对应一位固定的教师。由语义可得到如下函数依赖:(S,J)→T,(S,T)→J,T→J。该关系模式的候选码为(S,J),(S,T)。
因为该关系模式中的所有属性都是主属性,所以,STJ∈3NF,但STJ∉BCNF,因为T是决定因素,但T不包含码。不属于BCNF的关系模式,仍然存在数据冗余问题。如例3-12中的关系模式STJ,如果有100个学生选定某一门课,则教师与该课程的关系就会重复存储100次。STJ可分解为如下两个满足BCNF的关系模式,以消除此种冗余:TJ(T,J),ST(S,T)。
BCNF不仅强调其他属性对码的完全的直接的依赖,而且强调主属性对码的完全的直接的依赖,它包括3NF,即R∈BCNF,则R一定满足3NF。如果一个实体集中的全部关系模式都满足BCNF,则实体集在函数依赖范畴内已实现了彻底的分离,消除了插入和删除异常问题。3NF只强调非主属性对码的完全直接依赖,这样就可能出现主属性对码的部分依赖和传递依赖。
BCNF并不是最高范式,后面还有第4范式、第5范式,这里就不再详细介绍,有兴趣的同学可以查阅相关资料。
3.3.4 规范化小结
在关系数据库中,对关系模式的基本要求是满足1NF,在此基础上,为了消除关系模式中存在的插入异常、删除异常、更新异常和数据冗余等问题,人们寻求解决这些问题的方法,这就是规范化的目的。
规范化的基本思想是逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”。让一个关系描述一个概念、一个实体或实体间的一种联系,若多于一个概念就把它“分离”出去,因此,所谓规范化实质上是概念的单一化。
关系模式的规范化过程是通过对关系模式的分解来实现的,把低一级的关系模式分解为若干个高一级的关系模式,对关系模式进一步规范化,使之逐步达到2NF、3NF、4NF和5NF。各种规范化之间的关系为:
5NF⊆4NF⊆BCNF⊆3NF⊆2NF⊆1NF。
关系规范化的递进过程如图3-1所示。
图3-1 关系规范化的递进过程
一般来说,规范化程度越高,分解就越细,所得数据库的数据冗余就越小,且更新异常也可相对减少。但是,如果某一关系经过数据大量加载后主要用于检索,那么,即使它是一个低范式的关系,也不要去追求高范式而将其不断进行分解,因为在检索时,会通过多个关系的自然连接才能获得全部信息,从而降低了数据的检索效率。数据库设计满足的范式越高,其数据处理的开销也越大。
因此,规范化的基本原则如下:由低到高,逐步规范,权衡利弊,适可而止。通常,以满足第三范式为基本要求。
把一个非规范化的数据结构转换成第三范式,一般经过以下几步:
1)把该结构分解成若干个属于第一范式的关系。
2)对那些存在组合码且有非主属性部分函数依赖的关系必须继续分解,使所得关系都属于第二范式。
3)若关系中有非主属性传递依赖于码,则继续分解之,使得关系都属于第三范式。
事实上,规范化理论是在与SQL编程语言结合时产生的。关系理论的基本原则指出,数据库被规范化后,其中的任何数据子集都可以用基本的SQL操作获取,这就是规范化的重要性所在。数据库不进行规范化,就必须通过编写大量复杂代码来查询数据。规范化规则在关系建模和关系对象建模中同等重要。