当前位置:文档之家› 数据库-关系模式的设计-规范化

数据库-关系模式的设计-规范化

关系数据库设计目录第1章简介 (1)第2章函数依赖 (1)2.1 函数依赖的定义 (1)2.2 关系的键码 (2)2.3 超键码 (3)2.4 函数依赖规则 (3)2.4.1 分解/合并规则 (3)2.4.2 平凡依赖规则 (3)2.4.3 传递规则 (4)第3章模式设计 (4)3.1 问题的提出 (4)3.2 问题的根源 (5)3.2.1 完全依赖和部分依赖 (5)3.2.2 传递依赖 (6)3.3 解决的途径 (7)3.3.1 第1范式(1NF) (7)3.3.2 第2范式(2NF) (7)3.3.3 第3范式(3NF) (8)3.3.4 BC范式(BCNF) (8)3.4 分解的原则 (9)3.5 分解的方法 (12)3.5.1 模式分解的两个原则 (12)3.5.2 模式分解的3种方法 (13)3.5.3 把关系模式分解成BC范式的方法总结 (14)3.6 关系模式规范化小结 (15)第4章多值依赖 (16)4.1 属性独立性带来的冗余 (16)4.2 多值依赖的定义 (17)4.3 第4范式 (18)4.4 分解成第4范式 (18)第5章总结 (19)第1章简介关系数据库是由一组关系组成,所以关系数据库的设计归根到底是如何构造关系,即如何把具体的客观事物划分为几个关系,而每个关系又有哪些属性组成。

在我们构造关系时,经常会发现数据冗余和更新异常等现象,这是由于关系中个属性之间的相互依赖性和独立性造成的。

关系模型有严格的数学理论基础,并形成了关系数据库的规范化理论,这为我们设计出合理的数据库提供了有利的工具。

第2章函数依赖2.1 函数依赖的定义为了便于了解函数依赖(functional dependency)的概念,先看一个具体的关系实例。

例:考虑学生关系Student,该关系中涉及的属性包括学生的学号(Sno)、姓名(Sname)、所在系(Sdept)、系主任姓名(Mname)、课程名(Cname)和成绩(Grade)。

学生关系Student的实例如表1所示。

表 1 学生关系Student实例在这个实例中,我们可以看到属性之间存在某些内在的联系:由于一个学号值对应一个学生,一个学生只在一个系,因而当“学号”确定之后,姓名及所在系也就唯一确定了。

属性中的这种依赖关系类似于数学中的函数。

因此说Sno 函数决定Sname和Sdept,或者说Sname和Sdept函数依赖于Sno,记作Sno→Sname,Sno→Sdept。

下面给出函数依赖的严格定义:如果关系R的两个元组在属性A1,A2,…An上一致(也就是,两个元组在这些属性所对应的各个分量具有相同的值),则它们在另一个属性B上也一致。

那么,我们就说在关系R中属性B函数依赖于属性A1A2…An。

这种依赖正式记作A1A2…An→B,也就是说“A1,A2,…An函数决定B”。

其中,A1A2…An称为决定因素。

如果一组属性A1,A2,…An函数决定多个属性,比如说:A1A2…An→B1A1A2…An→B2…A1A2…An→Bm则可以把这一组依赖关系简记为:A1A2…An→B1B2…Bm例:在上例中,我们可以列举关于Student关系的以下四个函数依赖:Sno→SnameSno→SdeptSdept→MnameSno Cname→Grade由于前面的两个依赖的左边完全相同,都是Sno,用简写的形式可以把它们汇总在一行中:Sno→Sname Sdept根据函数依赖的传递规则,从Sno→Sdept和Sdept→Mname可以导出Sno→Mname。

这一点我们从感性认识上也很容易理解,一个学号对应唯一的学生,而一个学生只能有唯一的系主任。

另一方面,Sno→Cname就是错误的,它不是函数依赖,原因显而易见,如第1元组和第2元组,它们的Sno分量相同,但Cname分量却不同。

2.2 关系的键码我们已经了解了键码的概念,下面从函数依赖角度给出定义。

如果一个或多个属性的集合{A1,A2,…An}满足如下条件,则称该集合为关系R的键码(key):(1)这些属性函数决定该关系的所有其他属性。

也就是说,R中不可能有两个不同的元组,它们在A1,A2,…An上的取值是相同的。

(2){A1,A2,…An}的任何真子集都不能函数决定R的所有其他属性,也就说,键码必须是最小的。

例:在学生的关系中,属性集{Sno,Cname}构成Student关系的键码。

有时一个关系有多个键码。

例:在Student关系中我们可以加上属性身份证号(Idno),则关系中存在两个键码{Sno,Cname}和{Idno,Cname}。

2.3 超键码包含键码的属性集称为“超键码”(superkey),是“键码的超集”的简称。

因此,每个键码都是超键码。

但是,某些超键码不是键码。

例:在学生关系中有许多超键码,不仅键码{Sno,Cname}本身是超键码,而且该属性集的任何超集,如{Sno,Cname,Grade},{Sno,Sname,Cname}都是超键码。

2.4 函数依赖规则假设已知某关系所满足的函数依赖集,在不知道该关系的具体元组的情况下,通常可以推断出该关系必然满足的其他某些函数依赖。

例:如果已知关系R拥有属性A,B和C,它满足如下函数依赖:A→B和B→C,则断定R也满足依赖A→C。

下面介绍3个函数依赖规则。

2.4.1 分解/合并规则(1)我们可以把一个函数依赖A1A2…An→B1B2…Bm用一组函数依赖A1A2…An→Bi(i=1,2,…,m)来替代。

这种转换成为“分解规则”(splitting rule)。

(2)我们也可以把一组函数依赖A1A2…An→Bi(i=1,2,…,m)用一个依赖A1A2…An→B1B2…Bm来替代。

这种转换称为“合并规则”(combining rule)。

2.4.2 平凡依赖规则对于函数依赖A1A2…An→B1B2…Bm,(1)如果B是A的子集,则称该依赖为平凡依赖。

(2)如果B中至少有一个属性不在A中,则称该依赖为非平凡的。

(3)如果B中没有一个属性在A中,则称该依赖为完全非平凡的。

平凡依赖规则:函数依赖A1A2…An→B1B2…Bm等价于A1A2…An→C1C2…Ck,其中C是B的子集,但C不在A中出现。

我们称这个规则为“平凡依赖规则”(trivial dependency rule)。

若函数依赖满足平凡依赖规则,则该依赖为完全非平凡依赖。

2.4.3 传递规则传递规则使我们把两个函数依赖级联成一个新的函数依赖。

如果A1A2…An→B1B2…Bm和B1B2…Bm→C1C2…Ck在关系R中成立,则A1A2…An→C1C2…Ck在R中也成立。

这个规则就称为传递规则(transitive rule)。

第3章模式设计关系数据库设计理论主要用于知道数据库的逻辑设计,确定关系模式的划分,每个关系模式所包含的属性从而使得由一组关系模式组成的关系模式作为一个整体,既能客观描述各种实体,又能准确反映各种实体之间的联系,还能实地体现出实体内部属性之间的相互依存与制约。

3.1 问题的提出在设计数据库模式的时,特别是从面向对象的ODL设计或从E-R设计直接向关系数据库转换时,很容易出项的问题是冗余性,即一个事实在多个元组中重复。

而且,我们发现造成这种冗余的最常见的原因是,企图把一个对象的单指和多值特性包含在一个关系中。

例:在2.1节,当我们把学生的单指信息(如所在系)和多值特性(如课程集)存储子啊一起的时候,就导致了信息的冗余。

表 2 学生关系Student实例当我们企图把太多的信息存放在一个关系中时,就会出现数据冗余和更新异常等问题。

主要表现如下:(1)数据冗余。

信息可能在多个元组中不必要的重复。

如学生所在的系和系主任。

(2)修改异常。

我们可能修改了一个元组的信息,但另一个元组的相同信息却没有修改。

比如,计算机系的主任换了一个人,可能由于粗心,只修改了第1元组,而没有修改第2和第3元组。

于是出现数据不一致。

然而重新设计关系Student从而出现这种错误是完全可能的。

(3)删除异常。

如果一组属性的值变为空,带来的副作用可能是丢失一些信息。

比如,如果我们从学生晓雪的课程集中删除了自动化设计,那么数据库里就没有这个学生的课程信息了。

由于课程名和学号共同组成该关系的键码,而建立数据库时,键码属性不能为空,于是,关系Student中的晓雪的元组就会消失,同时消失的还有与晓雪有关的其他属性信息。

(4)插入异常。

刚开学,学生尚未选课,使得键码属性值缺少课程名,结果导致学生的基本情况(学号、姓名、所在系)甚至系主任姓名都不能插入。

这显然不符合道理。

3.2 问题的根源关系的键码函数决定该关系的所有其他属性,由于键码能唯一的确定一个元组,所以,也可以说关系的键码函数决定该关系的所有属性。

换句话说,一个关系中的所有属性都函数依赖于该关系的键码。

当我们进一步分析时,就会发现不同的属性在关系模式中所处的地位和扮演的角色是不同的。

再深入分析,又会发现不同的属性对键码函数依赖的性质和程度是有区别的。

有的属于直接依赖,有的属于间接依赖(通常称为传递依赖)。

当键码由多个属性组成时,有的属性函数依赖于整个键码属性集,而有的属性只函数依赖于键码属性集中的一部分属性。

3.2.1 完全依赖和部分依赖V (V是W的真子集)而函数依赖V→A成立,对于函数依赖W→A,如果存在W则称A部分依赖(partial dependency)于W,否则,若不存在这种V,则称A完全依赖(full dependency)于W。

从上述定义中可以得出一个结论:若W为单属性,则不存在真子集V,所以A必然完全依赖于W。

例:我们结合学生关系的例子具体说明完全依赖和部分依赖对冗余或异常有没有影响。

关系模式Student(Sno,Sname,Sdept,Mname,Cname,Grade)中(Sno,Cname)为键码,函数依赖集如下:Sno→Sname,SdeptSdept→MnameSno→MnameSno,Cname−→−P Sname,Sdept,MnameSno,Cname−→−F Grade可以看出属性Sname,Sdept和Mname都函数依赖于Sno,而部分依赖于键码,上面用P标记。

属性Grade则完全依赖于键码,上面用F标记。

观察表2关系Student的实例,就会注意到:对键码完全依赖的属性Grade没有任何的冗余,每个学生的每门课程都有特定的成绩(当然,两门课程的成绩完全相同是有可能的,但这并不意味着冗余)。

对键码部分依赖的属性Sname,Sdept和Mname由于只函数依赖于Sno,因此,当一个学生选修几门课时,这些数据就会多次重复出现,造成大量数据冗余;另一方面,当对一个学生的基本情况(学号、姓名、所在系)进行更新时,又会出现前面讨论过的异常。

相关主题