本篇讲解在开发应用系统时如何在已经选定的数据库管理系统基础上设计数据库,以及如何基于数据库系统编程。
本篇包括三章。
第6章关系数据理论,详细讲解关系规范化理论,它既是关系数据库的重要理论基础,也是数据库设计的有力工具。规范化理论为数据库设计提供了理论指南和工具。
第7章数据库设计,讨论数据库设计的方法和步骤,详细讲解数据库设计各阶段的目标、方法和应注意的问题;重点讲解概念结构和逻辑结构的设计。概念结构设计着重介绍实体-联系(E-R)模型的基本概念和设计方法。逻辑结构着重介绍把E-R模型转换为关系模型的方法。
第8章数据库编程,应用系统中可以采用多种方式来访问和管理数据库数据,本章讲解这些编程技术的概念和方法,包括嵌入式SQL、过程化SQL、存储过程及自定义函数,ODBC、OLE DB、JDBC等。
作为一个二维表,关系要符合一个最基本的条件:每一个分量必须是不可分的数据项。满足了这个条件的关系模式就属于第一范式(1NF)
在模式设计中,假设已知一个模式Sφ,它仅由单个关系模式组成,问题是要设计一个模式SD,它与Sφ等价,但在某些指定的方面更好一些。这里通过一个例子来说明一个不好的模式会有些什么问题,分析它们产生的原因,并从中找出设计一个好的关系模式的办法。
在举例之前,先非形式地讨论一下数据依赖的概念。
数据依赖是一个关系内部属性与属性之间的一种约束关系。这种约束关系是通过属性间值的相等与否体现出来的数据间相关联系。它是现实世界属性间相互联系的抽象,是数据内在的性质,是语义的体现。
人们已经提出了许多种类型的数据依赖,其中最重要的是函数依赖(Functional Dependency, FD)和多值依赖(Multi-Valued Dependency, MVD)。
【举例】建立一个描述学校教务的数据库,该数据库设计的对象包括学生的学号(Sno)、所在系(Sdept)、系主任姓名(Mname)、课程号(Cno)、和成绩(Grade)。假设用一个单一的关系模式Student来表示,则该关系模式的属性集合为
U={Sno, Sdept, Mname, Cno, Grade)
现实世界的已知事实(语义)告诉我们:
于是得到属性组U上的一组函数依赖F(如下图所示)
F={Sno->Sdept, Sdept->Mname, (Sno, Cno)->Grade}
如果只考虑函数依赖这一种数据依赖,可以得到一个描述学生的关系模式Student。下表是某一时刻关系模式Student的一个实例,即数据表。
Sno | Sdept | Mname | Cno | Grade |
---|---|---|---|---|
S1 | 计算机系 | 张明 | C1 | 95 |
S2 | 计算机系 | 张明 | C1 | 90 |
S3 | 计算机系 | 张明 | C1 | 88 |
S4 | 计算机系 | 张明 | C1 | 70 |
S5 | 计算机系 | 张明 | C1 | 78 |
… | … | … | … | … |
但是,这个关系模式存在以下问题:
1. 数据冗余
比如,每一个系的系主任姓名重复出现,重复次数与该系所有学生的所有课程成绩出现次数相同,如上表所示。这将浪费大量的存储空间。
2. 更新异常(update anomalies)
由于数据冗余,当更新数据库中的数据时,系统要付出很大的代价来维护数据库的完整性,否则会面临数据不一致的危险。比如,某系更换系主任后,必须修改与该系学生有关的每一个元组。
3. 插入异常(insert anomalies)
如果一个系刚成立,尚无学生,则无法把这个系及其系主任的信息存入数据库。
4. 删除异常(delete anomalies)
如果某个系的学生全部毕业了,则在删除该系学生信息的同时,这个系及其系主任的信息也丢掉了。
鉴于存在以上种种问题,可以得出这样的结论:Student关系模式不是一个好的模式。一个好的模式应当不会发生插入异常、删除异常和更新异常,数据冗余应尽可能少。
为什么会发生这些问题呢?
这是因为这个模式中的函数依赖存在某些不好的性质。这正是本章要讨论的问题。假如把这个单一的模式改造一下,分成三个关系模式:
S(Sno, Sdept, Sno->Sdept);
SC(Sno, Cno, Grade, (Sno, Cno)->Grade);
DEPT(Sdept, Mname, Sdept->Mname);
这三个模式都不会发生插入异常、删除异常的问题,数据的冗余也得到了控制。
那么,一个模式的数据依赖会有哪些不好的性质,如何改造一个不好的模式呢?
本节首先讨论一个关系属性间不同的依赖情况,讨论如何根据属性间依赖情况来判定关系是否具有某些不合适的性质,通常按属性间依赖情况来区分关系规范化程度为第一范式、第二范式、第三范式和第四范式等;然后直观地描述如何将具有不合适性质的关系转换为更合适的形式。
定义6.1 设R(U)是属性集U上的关系模式,X, Y是U的子集。若对于R(U)的任意一个可能的关系r, r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称X函数确定Y或Y函数依赖于X,记作X→Y。
下面介绍一些术语和记号。
定义6.2 在R(U)中,如果X->Y,并且对于X的任何一个真子集X’,都有Y不函数依赖于X’,则称Y对X完全函数依赖。
若X->Y,但Y不完全函数依赖于X,则称Y对X部分函数依赖(partial functional dependency)。
定义6.3在R(U)中,如果X->Y, Y->Z, 则称Z对X传递函数依赖(transitive functional dependency)。
设K为R中的属性或属性组合,若U完全函数依赖于K,则K为R的候选码
若候选码多于一个,则选定其中的一个为主码。
包含在任何一个候选码中的属性称为主属性;不包含在任何候选码中的属性称为非主属性。
关系模式R中属性或属性组X并非R的码,但X是另一个关系模式的码,则称X是R的外部码,也称外码。
一个低一级范式的关系模式通过模式分解可以转换为若干个高一级范式的关系模式的集合,这种过程就叫规范化。
若R∈1NF,且每一个非主属性 完全函数依赖于任何一个候选码,则R∈2NF。
下面举一个不是2NF的例子。 有关系模式S-L-C(Sno, Sdept, Sloc, Cno,
Grade),其中Sloc为学生的住处,并且每个系的学生住在同一个地方。S-L-C的码为(Sno, Cno)。则函数依赖有:
一个关系模式R不属于2NF,就会产生以下几个问题:
解决的办法是用投影分解把关系模式S-L-C分解为两个关系模式:SC(Sno, Cno, Grade)和S-L-C(Sno, Sdept, Sloc)。这就使得非主属性对码都是完全函数依赖了。
若R∈2NF,且不存在非主属性传递依赖于码,则R∈3NF。
在图6.4中关系模式SC没有传递依赖,而图6.5中关系模式S-L存在非主属性对码的传递依赖。在S-L中,由:Sdept函数依赖Sno,Sloc函数依赖Sdept,可得Sloc传递依赖于Sno。因此SC属于3NF,而S-L不属于3NF。
一个关系模式R若不是3NF,就会产生与2NF相类似的问题。插入异常、删除异常、更新复杂。
在关系模式R中,若每一个决定因素(箭头前面的东西)都包含码,则R∈BCNF。
一个满足BCNF的关系模式有:
举个不属于BCNF的例子: 关系模式STJ(S, T,
J)中,S表示学生,T表示教师,J表示课程。每一教师只教一门课,每门课有若干教师,某一学生选定某门课,就对应一个固定的教师。由语义可得到如下的函数依赖:
(S, J)->T, (S, T)->J, T->J
函数依赖关系可以用图6.6表示,这里(S, J)、(S, T)都是候选码。STJ是3NF,因为没有任何非主属性对码传递依赖或部分依赖,,但STJ不是BCNF关系,因为T是决定因素,而T不包含码。
3NF和BCNF是在函数依赖的条件下对模式分解所能达到的分离程度的测度。
一个模式中的关系模式如果都属于BCNF,那么在函数依赖范畴内它已实现了彻底的分离,已消除了插入和删除异常。3NF的“不彻底性”表现在可能存在主属性对码的部分依赖和传递依赖。
以上完全是在函数依赖的范畴内讨论问题。属于BCNF的关系模式是否就很完美了呢?下面来看一个例子。
学校中某一门课程由多个教师讲授,他们使用相同的一套参考书。每个教师可以讲授多门课程,每种参考书可以供多门课程使用。可以用一个非规范化的关系来表示教师T、课程C和参考书B之间的关系(如表6.3所示)。
把这张表变成一张规范化的二维表,如表6.4所示。
关系模型Teaching的码是 ,即all-key,因而Teaching∈BCNF。 但是当某一课程(如物理)增加一名讲课教师(如周英)时,必须插入多个(这里是三个)元组:(物理,周英,普通物理学),(物理,周英,光学原理),(物理,周英,物理习题集)。
同样,某一门课(如数学)要去掉一本参考书(如微分方程),则必须删除多个(这里是两个)元组:(数学,李勇,微分方程),(数学,张平,微分方程)。
因而对数据的增删改很不方便,数据的冗余也十分明显。仔细考察这类关系模式,发现它具有一种称之为多值依赖(Multi-Valued Dependency, MVD)的数据依赖。
例如,在关系模式Teaching中,对于一个(物理,光学原理)有一组T值{李勇,王军},这组值仅仅决定于课程C上的值(物理)。也就是说对于另一个(物理,普通物理学),它对应的一组T值仍是{李勇,王军}。尽管这时参考书B的值已经改变了。因此T多值依赖于C,即C->->T。3
4NF就是限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖。
函数依赖和多值依赖是两种最重要的数据依赖。如果只考虑函数依赖,则属于BCNF的关系模式规范化程度已经是最高了;如果考虑多值依赖,则属于4NF的关系模式规范化程度是最高的。事实上,数据以来中除函数依赖和多值依赖之外,还有其他的数据依赖。例如有一种连接依赖。函数依赖是多值依赖的一种特殊情况,而多值依赖实际上又是连接依赖的一种特殊情况。如果消除了属于4NF的关系模式中存在的连接依赖,则可以进一步达到5NF的关系模式。
注:关于数据依赖的公理系统以及模式分解,后续更新。
无损分解指的是对关系模式分解时,原关系模型下任一合法的关系值在分解之后应能通过自然联接运算恢复起来。反之,则称为有损分解。
保持函数依赖指的是对关系分解时,原关系的闭包与分解后关系闭包的并集相等。