-
1 设计不良好的关系...
-
2 函数依赖
-
3 不同类型的函数依赖
-
4 函数依赖集与属性...
-
5 Armstrong公理
-
6 函数依赖闭包和属...
-
7 极小函数依赖集
在这部分内容开始的时候。我们先提出三个问题:
1. 什么样的关系模式是不好的设计?
2. 如何判断一个关系模式的良好级别?
3. 如何把一个不好的关系模式转换成好的关系模式?如何判断转换的效果?
其实学习规范化理论这部分的内容的主要目的就是要回答这三个问题。让我们首先来看第1个问题“什么样的关系模式是不好的设计?”。为了更便于理解和回答这个问题,我们给出一个关系模式,大家来分析一下:
问题背景:
在学生管理的数据库中要存储学号、姓名、所在系、系地址、课程号和成绩。假定设计以下关系模式来表示上述信息:
SLC(Sno,Sname,Sdept,Loca,Cno,Grade)
请尝试分析这个关系模式有无问题?
在开始讨论这个模式的问题以前,我们先分析一下这个关系模式的主键应该是什么?Sno?Cno?抑或是Sdept?你应该不会忘记作为主键的条件:能够唯一标识关系中的每一个元组。所以根据这一限定条件,能够作为主键的只能是Sno和Cno的组合:(Sno,Cno),我们把这种由多个属性组合起来构成的主键称作是“联合主键”。因为一个学生可能选修多门课,一门课会被多个学生选修的缘故,导致Sno、Cno谁都不能独立地唯一标识关系中的每一个元组,Sdept就更不用说了。那么Sdept能不能作为联合主键的一部分呢?不能,因为主键同时还应该具有“最小性”原则,因此Sdept属性是多余的。最终我们知道这个关系模式的主键应该是(Sno,Cno)。
如果仅看这个关系模式,你未必会发现问题。我们给你一些样本性的数据,你再看看:
样本数据 1

分析:从样本数据1中,你大概可以注意到这样一个现象:系的相关信息被反复地存储。我们现在给出的系名和地址还仅仅是做一个简略的示范。如果给出真实、完整的系名和系地址的话,可能你会更加直观地观测到这一点。我们就把这种不必要地重复存储相同数据的现象称作“数据冗余”。
这会带来什么样的后果呢?两个方面:
第1,数据被反复存储会浪费数据库的存储空间。
第2,当系的名称或地址发生变化的时候,我们需要修改的数据量非常大。
所以“数据冗余”对于数据库来讲是一种不好的现象。
样本数据 2

分析:“样本数据2”中的数据出现了变化,变化的原因是因为用户将“王文涛”的学号改成了“04015”。先不管用户是有意,还是无意地做出了这样的修改,我们只想讨论一下这样的修改会出现什么问题?问题是:“崔勇”和“王文涛”的学号居然相同!这违背了我们的常识:学号对于每一个学生来讲都应该是唯一的。但是遗憾的是数据库并没有发现这个错误,昏昏然地接受了用户这绝对错误的数据修改。为什么呢?答案就是我们一开始就讨论过的主键问题。因为这个关系模式的主键是(Sno,Cno),所以对主键唯一性的违反必须满足Sno和Cno同时相同。而此处仅仅是Sno相同,所以根据此处的关系模式设计,数据库不可能意识到这个违背常识的错误,依然会坚定地认为这是合法的数据,从而接受修改。显然数据库不应该为你背锅,只能怪罪于你自己的设计出现了问题。我们把这样的情况称作是“修改异常”。
样本数据 3

分析:秋高气爽的九月,我们迎来了新同学。他们在“风雨操场”中挥汗如雨地军训着,课程暂时和他们无关。所以就出现了样本数据3中的情形:一些同学没有选择课程。其实你在真正的关系中是不可能看到未选课程的学生信息的,因为数据库会拒绝你插入类似的信息。为什么呢?原因离不开主键。因为Cno是主键的一部分,而主键的特点之一是不能为空,所以数据库会毫不犹豫地拒绝你插入未选课的学生数据。这样的情况被称做“插入异常”。
样本数据 4

分析:热情似火的七月,我们计算机系送走了毕业的师兄师姐们。他们的信息,我们也将从数据库中删除。之后你就看到了类似样本数据4的结果。发生了什么?计算机系不存在了!因为计算机系目前所有的学生都毕业,信息都被删除了,所以计算机系也随着毕业的学生一起被毕业了。这就尴尬了!虽然当前的学生毕业了,但我们肯定是想保留计算机系,迎接下一届新生!所以这样的删除也是存在问题的。我们把这样的现象称作是“删除异常”。
通过对以上四种情况的分析,让我们来回答第1个问题:
问题:什么样的关系模式是不好的设计?
回答:如果一个关系模式中含有数据冗余、插入异常、更新异常和删除异常,则该关系模式是设计不良好的。
我们既然知道了只要出现“数据冗余”、“修改异常”、“插入异常”和“删除”现象的关系模式就是设计不良好的关系模式,那么我们如何才能避免这些现象的出现呢?
要避免,首先得知道产生异常的原因。这里我们直接抛出原因:原关系模式的设计直接将多个实体(学生、课程、系)不加区分、简单粗暴地放到了一个关系模式中,或者说一个关系模式中包含了多个实体或联系,违背了“一事一地”的原则。
解决办法:遵循“一事一地”的原则设计关系模式,即一个实体或一个多对多联系用一个关系模式表示。
下面给出采用“一事一地”原则改进后的关系模式:
students(Sno,Sname,Sdept) 关系模式:学生(实体)
courses(Cno) 关系模式:课程(实体)
sdepts(Sdept,Loca) 关系模式:系(实体)
sc(Sno,Cno,Grade) 关系模式:选课(联系)
大家可以看出:每一个关系模式都仅仅描述了一种实体或一种联系,这就是“一事一地”的概念。至于这个结果到底是如何得到的?采用的改进方法是什么?你将会在第3个问题的回答中看到这一点,也就是模式分解的概念。

