2.1 关系数据库的结构
关系数据库由一组表组成,每个表都分配了一个唯一的名称。例如,考虑图2.1的指导员表,表格里储存了指导员们的信息。这个表格有四列,分别是ID、姓名、dept_name、薪水。这个表格的每一行都记录着一位指导员的信息。相似的,图2.2的课程表储存课程信息。每一门课程的信息都有课程标识、名称、dept_name以及学分。注意,每位指导员是利用ID列来辨别的,而每个课程是利用课程标识来辨别的。
图2.3是第三个表格,如本例中的版本,这个表格储存了每个课程的前提课程。这个表格有两列,分别是课程标识和先决条件。每一行有两个课程,第二个课程是第一个课程的前提。
因此,在这个表格的每一行暗示着在某种意义上,两个课程中,其中一个课程是另一个课程的前提。
再如,我们再来考虑教师表,表格的每一行可以被认为是呈现唯一的ID、一致的名字、部门名称和薪水这四个关系。
通常来说,表格的每一行代表着一组值的关系。因为表是这种关系的集合,在表格的概念与数学概念之间的关系存在一致,关系数据模型就是它的名称。用数学的专业用语,一个元组简单的值序列(或列表)。n值之间的关系用数组n来表示。换言之,一个数组有n个值,这与表格中的每一行相符合。
因此,在关系模型中,术语关系用于引用表,术语元组用于引用行。相似的,术语属性用于引用列。
例如表2.1,我们可以看到指导员表有四列,分别是ID、姓名、dept_name、薪水。
我们使用术语实例来引用关系的特定实例。换言之,包含了一组特定行。图2.1中指导员的实例表明了有12个元组,符合12位指导员的信息。
在本章,我们使用许多不同的潜在的关系数据模型来说明各种各样的概念。这些关系代表了大学的一部分,它们没有包括实际上一个大学数据库所能包括的全部数据,是因为要简化其呈现。我们应该讨论适合关系结构的标准用于章节7和8.
一个关系与元组元素的顺序是不相干的,因为一个关系是一组数组。因此,是否关系数组排列是按顺序,如图2.1,或者是不按顺序排列,如图2.4,都是没有关系的。这个关系在两个图表中都是一样的。因为两个都包含了一样的一组数组。为了便于解释,我们大部分的关系都是按照第一个属性来分类的。
每个关系中包含的每个属性,都有一组允许值,称作属性范围。薪水范围是所有指导员薪水值的属性范围,所有指导员的名字范围也是指导员名字的属性范围。
我们须知,对于所有的关系r,所有属性r是有原子域。一个原子域的要素被认为是不可分的结合。例如,假设指导员表有电话号码这个属性,可以储存每一位指导员的电话号码。然而这个电话号码是无原子域的,因为元组元素的范围是一组电话号码,它有其组成,即个人的电话号码在集合中。
重要的问题不是它本身的范围而是我们数据所要用到的范围。假设电话号码这个属性只存储了一个号码,甚至,我们将电话号码的这些值分割转变成国家代码、地区区号和本地号码,我们可把它当做无原子域。如果我们尝试将每个电话号码当做一个单一的不可分的结合,那么电话号码就会有一个原子域。
在这一章,以及在第3章到第6章,我们假设所有的属性都有原子域。在第22章,我们扩大关系数据模型以此来允许无原子域。
空值是一个特殊的值,它代表着值是未知的或不存在的。例如,假设之前我们将电话号码包含在指导员表的属性当中,代表指导员根本就没有电话号码或者电话号码没有被列举进来。我们这个时候用空值去表示不知道或者不存在。我们稍后就可以看到空值在我们要评估或更新数据时造成了许多困难,因此要尽可能的排除。我们假定空值是最初就不存在,在第3.6部分我们会介绍在不同操作中空值对其的影响。
2.2数据库模式
当我们提到数据库,我们应该要与数据库模式区别开来,数据库模式是为数据库所设计的逻辑。数据库实例是在数据库中在短时间内数据的快照。
一个关系概念符合于程序语言的变量,而关系模式的概念符合于程序语言的类型定义。
通常来说,一个关系模式由一系列的属性及其范围组成。在我们学到第3章SOL语言之前,我们暂时不用考虑先前定义属性的范围。
关系案例的观点符合于变量值的概念,所给的变量值可能会随着时间的改变而改变。相似的关系案例的项目内容也会随时间改变而改变,更新。相反的,关系模式通常不会改变。
虽然了解关系模式和关系实例之间的区别是十分重要的,但是我们经常使用同样的名字,例如用指导员来引用模式和案例。在需要时,我们就明确的引用到模式或到实例。例如,“指导员模式”或者“指导员关系案例”。然而,在这里我们可以清楚的知道表达的是模式还是案例,我们仅仅用关系名称。
认真思考图2.5的住宅关系,这个模式关系包括(dept_name、建筑、预支)
注意,dept_name名称既出现在教学模式又出现在部门架构。这个重复并不是一个巧合。而是,通常使用认为关系模式是一种连接另一关系元组的一种方法。例如,假设我们想找到哪位指导员是在沃森,我们第一件事就是查找所有在沃森的部门,然后我们相比对查找是否有一致的。
让我们继续大学数据库的例子。
大学中每个课程都有可能被增加学习时长,跨越不同的学期或在学期之内。在班级,我们需要一个关系去描述个人的需求或选择。这个模式包括:课程标识、SEC的ID、学期、年份、楼、房号、时间空挡。
图2.6显示了一个部分关系的实例。
我们需要一个关系去描述指导员和他们所教学的课程的关系。关系模式来描述就是图2.7,说明了指导员关系也是一样的情况。
正如你所想象的,有许多关系包含在大学数据库中,除了我们已经列举的这些关系,指导员、地址、课程、部分先前条件和教学。在课本中我们使用以下关系:
(1)学生(ID、name、dept_name、tot_cred)
(2)建议者(s_id、i_id)
(3)持有(ID、课程标识、sec_id、学期、年份、年级)
(4)教室(建筑、门牌号、容量)
(5)时间(空闲时间、开始时间、结束时间)
2.3键
我们必须有一个方法来指定给定关系中的元组是如何消除的。这是用它们的属性来表示的。也就是说,元组属性值的值必须使它们能够唯一的标识元组。换句话说,关系中的任何两个元组都不允许具有完全相同的值的格式属性。
超级键是一组由一个或多个属性组成的集合,这些属性集合在一起,允许我们唯一地标识关系中的一个元组。例如,关系指导员的ID属性足以区分一个指导员元组和另一个指导员元组。因此,ID是一个超级键。另一方面,指导员的名字不是超级键,因为指导员的名字可能是相同的。
形式上,让R表示关系,模式r中的属性集。如果我们说R的一个子集K是r的一个超级键,那么我们就限制了关系r的例子,其中没有两个不同的元组对K中的所有属性都有相同的值。那就是说,如果t1和t2都在t中且t1不等于t2,所以K.t1不等于K.t2.
超级键可以包含无关的属性。例如,ID和姓名的组合是关系指导员。如果K是一个超级键,那么任何K的超集也是如此。我们经常对没有子集的超级键感兴趣。这种最小的超集键称为候选键。
有可能有几组不同的属性可以作为候选键。假设名字和dept_name的组合足以区分指导员关系的成员。然后,{ID}和{name,dept_name}都是候选键。虽然属性ID和名字一起可以区分指导员组,但它们的组合{ID,name}并不构成候选键,因为属性ID本身就是候选键。
我们将使用主键一词来表示数据库设计器选择的候选键作为识别关系中元组的主要手段。键(无论是主键、候选键还是超级键)是整个关系的属性。关系中的任何两个单独的元组都不能同时对关键属性具有相同的值。键的指定代表了正在建模的现实世界企业中的一个约束。
必须谨慎地选择主键。正如我们所说,一个人显然是不够的,因为有许多同名的人。在美国,一个人的社会保障号码属性将是一个候选密钥。因为非美国居民通常没有社会保障号码,国际企业必须产生自己独特的标识符。另一种方法是使用其他属性的一些独特组合作为键。
主键应该要被选择,这样它的属性值永远不会改变或者很少改变。例如,一个人的地址字段不应该是主键的一部分,因为它很可能会改变。另一方面,社会保障数字保证不会改变。企业产生的唯一标识符一般不改变,除非两个企业合并;在这种情况下,两个企业可能都发出相同的标识符,并且可能需要重新分配标识符以确保它们是唯一的。
通常在其他属性之前列出关系模式的主键属性;例如,首先列出部门的dept_name属性,因为它是主键。主键属性也包括下划线。
一个关系,比如说r1,可以再它的属性中包含另一个关系的主键,比如r2。这个属性称为r1中的外键,引用r2。关系r1也称为外键依赖的引用关系,r2称为外键的引用关系。例如,因为dept_name是deyarding的主键,所以指导员中的属性dept_name是来自指导员引用部门的外键。在任何数据库实例中,给定任何元组(例如ta),来自指导员关系。在部门关系中必须有一些元组,比如tb,这样ta的dept_name属性的值与tb的主键dept_name的值相同。
现在考虑教授关系这一节。合理的要求是,如果某门课程有一节课,则必须至少有一名老师教学。然而,可能有一名以上的老师授课这一节课。为了执行这个约束,我们将要求如果一个特定的(课程标识、sec_id、学期、年份)组合出现在节中。然而,这组值并不构成教学的主键,因为不止一个老师可以教学这一部分。因此,我们不能申明一个外键约束从一个节到另一个部分(尽管我们可以在另一个方向定义一个外键约束,从一个外键约束到一个节)。从节到教学的约束是引用完整性的一个例子。
从节到TES的约束是引用完整性约束的一个示例;引用完整性约束要求在引用关系中的任何元组的指定属性中出现所引用关系中至少一个元组的指定属性中。