Access 2010数据库基础教程
上QQ阅读APP看书,第一时间看更新

1.3.2 关系规范化

1.第一范式(1NF)

如果关系模式R中每个属性值都是一个不可分解的数据项,则称该关系模式满足第一范式(1NF),记为R∈1NF。

第一范式规定了一个关系中的属性值必须是“原子”的,它排斥了属性值为元组、数组或某种复合数据的可能性,使得关系数据库中所有关系的属性值都是“最简形式”,这样要求的意义在于可能做到起始结构简单,为以后复杂情形讨论带来方便。一般而言,每一个关系模式都必须满足第一范式,1NF是对关系模式的起码要求。

非规范化关系转化为1NF的方法很简单,当然也不是唯一的,对表1-12和表1-13分别进行横向和纵向展开,即可转化为表1-14和表1-15所示的符合1NF的关系。

表1-14 具有组合数据项的规范化关系

表1-15 具有多值数据项的规范化关系

但是,满足第一范式的关系模式并不一定是一个好的关系模式。例如,关系模式SLC(SNO,DEPT,SLOC,CNO,GRADE),其中关系SLC中,SNO为学号,DEPT为系名,SLOC为学生住处,CNO为课号,GRADE为成绩。假设每个学生住在同一地方,SLC的码为(SNO,CNO)。

显然,SLC满足第一范式。这里(SNO,CNO)两个属性一起函数决定GRADE。(SNO,CNO)也函数决定DEPT和SLOC。但实际上仅SNO就函数决定DEPT和SLOC,因此非主属性DEPT和SLOC部分函数依赖于码(SNO,CNO)。完全依赖用F表示,部分依赖用P表示。函数依赖包括:

SLC关系存在以下3个问题:

(1)插入异常

假若要插入一个SNO="95102",DEPT="IS",SLOC="N",但还未选课的学生,即这个学生无CNO,这样的元组不能插入SLC中,因为插入时必须给定码值,而此时码值的一部分为空,因而该学生的信息无法插入。

(2)删除异常

假定某个学生只选修了1门课,如99022号学生只选修了3号课程,课程3是主属性,删除了课程号3,整个元组就不能存在了,也必须随之删除,从而删除了99022号学生的其他信息,产生了删除异常,即不应删除的信息也删除了。

(3)数据冗余度大

如果一个学生选修了10门课程,那么他的DEPT和SLOC值就要重复存储10次。并且当某个学生从数学系转到信息系,这只是一件事,只需要修改此学生元组中的DEPT值。但因为关系模式SLC还含有系的住处SLOC属性,学生转系将同时改变住处,因而还必须修改元组中SLOC的值。另外,如果这个学生选修了10门课,由于DEPT,SLOC重复存储了10次,当数据更新时必须无遗漏地修改10个元组中全部DEPT,SLOC信息,这就造成了修改的复杂化,存在破坏数据一致性的隐患。因此,SLC不是一个好的关系模式。

2.第二范式(2NF)

如果一个关系模式R∈1NF,且它的所有非主属性都完全函数依赖于R的任一候选码,则R∈2NF。

关系模式SLC出现上述问题的原因是DEPT,SLOC对码的部分函数依赖。为了消除这些部分函数依赖,可以采用投影分解法,把SLC分解为两个关系模式:

SC(SNO,CNO,GRADE)

SL(SNO,DEPT,SLOC)

其中,SC的码为(SNO,CNO),SL的码为SNO。

显然,在分解后的关系模式中,非主属性都完全函数依赖于码了,从而使上述3个问题在一定程度上得到部分的解决。

①在SL关系中可以插入尚未选课的学生。

②删除学生选课情况涉及的是SC关系,如果一个学生所有的选课记录全部删除了,只是SC关系中没有关于该学生的记录了,不会牵涉到SL关系中关于该学生的记录。

③由于学生选修课程的情况与学生的基本情况是分开存储在两个关系中的,因此不论该学生选多少门课程,他的DEPT和SLOC值都只存储了一次,这就大大降低了数据冗余程度。

④由于学生从数学系转到信息系,只需修改SL关系中该学生元组的DEPT值和SLOC值,由于DEPT,DLOC并未重复存储,因此简化了修改操作。

2NF不允许关系模式的属性之间有函数依赖X→Y,其中X是码的真子集,Y是非主属性。显然,码只包含一个属性的关系模式,如果属于1NF,那么它一定属于2NF,因为它不可能存在非主属性对码的部分函数依赖。

上例中的SC关系和SL关系都属于2NF。可见,采用投影分解法将一个1NF的关系分解为多个2NF的关系,可以在一定程度上减轻原1NF关系中存在的插入异常、删除异常、数据冗余度大等问题。

但是将一个1NF关系分解为多个2NF的关系,并不能完全消除关系模式中的各种异常情况和数据冗余。也就是说,属于2NF的关系模式并不一定是一个好的关系模式。

例如,2NF关系模式SL(SNO,DEPT,SLOC)中有下列函数依赖。

SNO→DEPT

DEPT→SLOC

SNO→SLOC

由上可知,SLOC通过DEPT传递函数依赖于SNO,即SL中存在非主属性对码的传递函数依赖,SL关系中仍然存在删除异常、数据冗余度大和修改复杂的问题。

①删除异常:如果某个系的学生全部毕业了,在删除该系学生信息的同时,把这个系的信息也丢掉了。

②数据冗余度大:每一个系的学生都住在同一个地方,关于系的住处的信息却重复出现,重复次数与该系学生人数相同。

③修改复杂:当学校调整学生住处时,比如信息系的学生全部迁到另一地方住宿,由于关于每个系的住处信息是重复存储的,修改时必须同时更新该系所有学生的SLOC属性值。

所以,SL仍然存在操作异常问题。仍然不是一个好的关系模式。

3.第三范式(3NF)

如果一个关系模式R∈2NF,且所有非主属性都不传递函数依赖于任何候选码,则R∈3NF。

关系模式SL出现上述问题的原因是SLOC传递函数依赖于SNO。为了消除该传递函数依赖,可以采用投影分解法,把SL分解为两个关系模式:

SD(SNO,DEPT)

DL(DEPT,SLOC)

其中,SD的码为SNO,DL的码为DEPT。

显然,在关系模式中既没有非主属性对码的部分函数依赖也没有非主属性对码的传递函数依赖,基本上解决了上述问题。

①DL关系中可以插入不在校学生的院系信息。

②某个系的学生全部毕业了,只是删除SD关系中的相应元组,DL关系中关于该系的信息仍然存在。

③关于系的住处的信息只在DL关系中存储一次。

④当学校调整某个系的学生住处时,只需修改DL关系中一个相应元组的SLOC属性值。

3NF不允许关系模式的属性之间有函数依赖X→Y,其中X不包含码,Y是非主属性。X不包含码有两种情况:一种情况X是码的真子集,这也是2NF不允许的;另一种情况X含有非主属性,这是3NF进一步限制的。

上例中的SD关系和DL关系都属于3NF。可见,采用投影分解法将一个2NF的关系分解为多个3NF的关系,可以在一定程度上解决原2NF关系中存在的插入异常、删除异常、数据冗余度大、修改复杂等问题。

但是,将一个2NF关系分解为多个3NF的关系后,并不能完全消除关系模式中的各种异常情况和数据冗余。也就是说,属于3NF的关系模式虽然基本上消除大部分异常问题,但解决得并不彻底,仍然存在不足。

例如,模型SC(SNO,SNAME,CNO,GRADE),如果姓名是唯一的,模型存在两个候选码:(SNO,CNO)和(SNAME,CNO)。

模型SC只有一个非主属性GRADE,对两个候选码(SNO,CNO)和(SNAME,CNO)都是完全函数依赖,并且不存在对两个候选码的传递函数依赖,因此SC∈3NF。

但是当学生退选了课程,元组被删除也失去学生学号与姓名的对应关系,因此仍然存在删除异常的问题;并且由于学生选课很多,姓名也将重复存储,造成数据冗余。因此3NF虽然已经是比较好的模型,但仍然存在改进的余地。

4.BCNF范式

若关系模式R∈1NF,对任何非平凡的函数依赖X→Y(Y⊄X),X均包含码,则R∈BCNF。

BCNF是从1NF直接定义而成的,可以证明,如果R∈BCNF,则R∈3NF。

由BCNF的定义可以看到,每个BCNF的关系模式都具有如下3个性质。

①所有非主属性都完全函数依赖于每个候选码。

②所有主属性都完全函数依赖于每个不包含它的候选码。

③没有任何属性完全函数依赖于非码的任何一组属性。

如果关系模式R∈BCNF,由定义可知,R中不存在任何属性传递函数依赖于或部分依赖于任何候选码,所以必定有R∈3NF。但是,如果R∈3NF,那么R未必属于BCNF。

如果一个关系数据库中的所有关系模式都属于BCNF,那么在函数依赖范畴内,它已实现了模式的彻底分解,达到了最高的规范化程度,消除了插入异常和删除异常。

BCNF是对3NF的改进,但是在具体实现时有时是有问题的。例如,下面的模型SJT(U,F)中(注,U是属性集,F是依赖集):

U=STJ,F={SJ→T,ST→J,T→J}

码是ST和SJ,没有非主属性,所以STJ∈3NF。

但是,非平凡的函数依赖T→J中T不是码,因此SJT不属于BCNF。

而当用分解的方法提高规范化程度时,将破坏原来模式的函数依赖关系,这对于系统设计来说是有问题的。这个问题涉及模式分解的一系列理论问题,在这里不再做进一步的探讨。

在信息系统的设计中,普遍采用的是“基于3NF的系统设计”方法,就是由于3NF是无条件可以达到的,并且基本解决了“异常”的问题,因此这种方法目前在信息系统的设计中仍然被广泛地应用。

如果仅考虑函数依赖这一种数据依赖,属于BCNF的关系模式已经很完美了。但如果考虑其他数据依赖,如多值依赖,属于BCNF的关系模式仍存在问题,不能算是一个完美的关系模式。