2.1关系数据库的结构
一个关系数据库由表的集合组成,其中每个表都有一个独一无二的名字。例如,考虑图2.1这张instructor表,它储存了关于教师们的信息。这张表有四个列标头:身份ID,名字,部门名称和工资。该表的每一行记录着一个教师的信息,包括这名教师的ID,名字,部门名称和工资。相似的,图2.2这张course表储存了关于课程的信息,包括每一个课程的课程编号,课程名字,课程所属科目和学分。注意每个教师被ID这一列的值标识,同时每门课被课程编号这一列的值标识。
表2.3显示了第三张表prereq,它储存了每门课的先修课。这张表有两列,课程编号和先修课编号。每一行包括一对课程标识符,其中第二门课是第一门课的先修课。
因此,prereq表中的一行指两门课的联系在这种意义上是一门课是另一门的先修课。再例如,我们考虑instructor表,表中的一行可被认为代表一个明确的ID和对应的名字,部门名称以及工资的值的关系。
总的来说,表中的一行代表一组值的关系。自从一张表是一组这样的关系的集合,在表的概念和关系的数学概念之间有了一个很近的关联,从中关系数据模型得到了它的名字。在数学的术语中,一个元组仅仅是一组值的数列(或名单)。n值间的关系被n元组的值在数学上代表,即,n值的一个元组在一张表中与一行相符合。
因此,在关系模型中,术语关系被用来指一张表,同时术语元组被用来指一行。相似地,术语属性指一张表的一列。
仔细看表2.1,我们可以看到关系instructor有四个属性:ID ,名字,部门名称和工资。
我们用术语关系实例来指一个明确的关系的例子,即,包含一系列明确的行。显示在表2.1Instructor中的例子有12个元组,与12个教师相对应。
在这个章节中,我们用许多不同的关系来说明各种各样的基础的关系数据模型的概念。这些关系代表大学的一部分。它们不包括所有的现在一个大学数据库所包含的数据,为了简化我们的报告。我们应详细地讨论在第7章和第8章中适当的关系结构的准则。
在关系中元组出现的顺序是不相干的,从一个关系是一组元组起。因此,是一个关系的元组被按顺序排列,像在表2.1一样,还是不被排序,像在表2.4一样,并没有关系;在两张表中的关系是相同的,从它们都包括相同的一组元组。为了便于解释,我们大多将显示被它们的第一个属性分类的关系。
对于一个表中的每个属性,这里有一组被允许的值,被叫做那个属性的域。因此,instructor关系的工资属性中的域是一套所有可能的工资值,同时名字属性的域是一套所有可能的教师名字。
我们要求,对所有关系r,r的所有属性的域是原子的。一个域是原子的,如果域的元素被认为是不可分的单位。例如,应该表instructor有一个属性电话号码,它可储存一系列对应于教师的电话号码。然后电话号码这个属性将不是原子的,从域的一个元素是一组电话号码,和它有分部,在集合中命名个人的电话号码。
最重要的问题不是域本身是什么,而是我们在我们的数据库中怎样用域元素。现在认为电话号码这个属性储存了一个单独的电话号码。尽管那样,如果我们分离从电话号码属性到一个国家代码,一个地区代码和一个当地代码的值,我们将它作为一个无原子的值对待。如果我们将每个电话号码作为一个单独的不可分割的集合对待,然后电话号码属性将会有一个原子的域。
在这章中,和在第三章到第六章中,我们认为所有属性有原子的域。在第22章中,我们会讨论延伸到关系数据模型来允许非原子的域。
空值是一个特殊的意味着值不被知道或不存在的值。例如,认为和以前一样我们在instructor关系中包括了属性电话号码。它可能是一个教师没有一个电话号码,或者电话号码不在列表中。然后我们将用空值表示值是不知道或不存在的。我们应看到以后空值造成许多困难当我们进入或更新数据库时,和因此应该被排除如果可能的话。我们会假设空值最开始是不存在的,在3.6部分,我们描述在不同的操作中空值的影响。
2.2数据库模式
当我们讨论数据库时,我们必须区分数据库模式,即数据库的逻辑设计,以及数据库实例,它是数据库中的数据在给定的时间内的快照。
关系的概念相当于变量的编程语言概念,而关系模式的概念相当于类型定义的编程语言概念。
通常,关系模式由属性列表及其对应域组成。在讨论第3章的SQL语言之前,我们不必关心每个属性的域的精确定义。
关系实例的概念对应于变量值的编程语言概念。给定变量的值可能会随时间而改变;同样地,当关系被更新时,关系实例的内容可能会随着时间而改变。相反,关系的模式通常不会改变。
虽然知道关系模式和关系实例之间的区别很重要,但是我们经常使用相同的名称,例如教员,来引用模式和实例。在需要时,我们直接地引用模式或实例,例如“教员模式”或“教员关系的实例”。然而,当我们明确表示模式或实例时,我们只使用关系名称。考虑图2.5的部门关系。这种关系的模式是部门(部门名称、建筑、预算)。
我们注意到,属性部门名称出现在教员模式和部门模式中,这种重复并非巧合。相反,在关系模式中使用公共属性是关联不同关系元组的一种方法。例如,假设我们希望找到关于在沃森大楼工作的所有教师的信息。我们先看看部门关系,找出所有在沃森的部门的部门名称。然后,对于每个这样的部门,我们在教师关系中查找与相应的部门名称相关的教员的信息。
让我们继续我们的大学数据库示例。
每门课程在大学可能会多次提出,在不同的学期,或者甚至在一个学期内。我们需要一个关系来描述这个类的每个单独的课程或一节课。模式是section (course_id, sec_id, semester, year, building, room_number, time_slot_id)。
图2.6显示了部分关系的一个示例实例。我们需要一个关系来描述教师和他们所教授的课程部分之间的联系。描述该关联的关系模式是teaches (ID, course id, sec id, semester,year)
图2.7显示了教授关系的示例实例。
你可以想象到,在真实的大学数据库中有更多的关系。除了这些我们已经列出来的关系, instructor, department,course,section,prereq,andteaches,我们在本文使用以下关系:
• student (ID, name, dept name, tot cred)
• advisor (s id, i id)
• takes (ID, course id, sec id, semester, year, grade)
• classroom (building, room number, capacity)
• time slot (time slot id, day, start time, end time)
2.3 码键
我们必须有一种方法来详细说明一个给定关系中的元组是如何区分的。这是根据它们的属性来表示的。也就是说,元组的属性值的值必须是它们唯一标识元组的值。换句话说,一个关系中没有两个元组对所有属性都具有完全相同的值。
一个超键是一个或多个属性设置,采取全体地,让我们唯一标识关系中的元组。例如,教员关系中的ID属性足以从一个教员元组中区分另一个教员元组。因此,ID是一个超键。教员的名字属性,从另一个方面来说,不是一个超键,因为几位教员可能具有相同的名字。
形式上,让R代表关系r模式中的属性集。如果说R的子集K是一个r的超键,我们将限制考虑关系r的例子,没有任何两个不同的元组在K中的所有属性的值都相同。换句话说,如果t1和t2在R中,且t1不等于t2,那么t1.K不等于t2.K。
一个超键可能包含额外的属性。例如,ID和名称的组合是教员关系的一个超键。如果K是一个超键,那么是任何含K的超集的超键。我们常常对没有适当子集的超键感兴趣,这种没有多余属性的超键被称为候选键。
这几个不同的属性集可以作为一个候选键是可能的。假设name和dept_name的组合足以区分在成员之中的教员关系。那么,{ID}和{name,dept_name}都是候选键。尽管属性ID和name一起可以区分教员的元组,但是它们的组合{ID, name}, 不能形成一个候选键,因为属性ID单独是一个候选键。
我们应该使用术语主码来表示被数据库设计器选择的候选键作为辨别一个关系中的元组的最主要的方法。键(无论是主键、候选键还是超键)是整个关系的属性,而不是单个元组的属性。任何关系中的任意两个元组都不能同时在键属性上具有相同的值。指定一个键表示正在建模的真实世界企业中的约束。
主键必须小心选择。我们注意到,一个人的名字不是足够有效的,因为可能有许多人有相同的名字。在美国,一个人的社会保障号码是一个候选键。由于非美国居民通常没有社会保障号码,国际企业必须形成他们自己独特的身份识别者。另一种方法是使用一些其他属性的特殊组合作为键。
主键应该被选中,这样它的属性值就不会,或者非常罕见地发生变化。例如,一个人的地址字段不应该是主键的一部分,因为它可能会发生变化。另一方面,社会保障号码是绝对不会改变的。企业产生的唯一标识通常不会改变,除非两家企业合并;在这种情况下,两个企业都可能发出相同的标识符,并可能需要重新分配标识符,以确保它们是唯一的。
习惯上,在其他属性之前列出关系模式的主要关键属性;例如,部门的dept_name属性首先列出,因为它是主键。主键属性也有下划线。
r1这样的一个关系,可能包括它的属性中另一个关系的主键,比如r2。这个属性在r1中被称为外键,引用了r2。关系r1也被称为外键依赖关系的引用关系,r2被称为外键的引用关系。例如,instructor的属性dept_name是来自instructor的外键,引用了department,因为dept-name是department的主键。在任何数据库实例中,给出的任何元组,比如ta,从instructor关系,必须有一些元组,比如tb,在department 关系中ta的dept-name属性的值与主键、dept-name与tb的相同。
现在考虑section和teaches关系。如果有一节课是存在的,那就必须由至少一名教师来教授;然而,它可能由不止一个教师来教授。为了执行这个约束,我们要求如果一个特定的 (course id, sec id, semester, year) 组合出现在section中,那么相同的组合必须出现在teaches。然而,这组值并不构成teaches的主键,因为不止一个教师可以教一个这样的部分。因此,我们不能从一节中声明一个外键约束(尽管我们可以在另一个方向定义外键约束,从teaches 到section)。
从teaches到section的约束是参照完整性约束的一个例子;引用完整性约束要求在引用关系中任何元组的指定属性中出现的值也会出现在引用关系中至少一个元组的指定属性中。
转自:《Database.System.Concepts》的【2.1 Structure of Relational Databases】至【2.3 Keys】