2.2 关系模型与关系数据库
关系数据库是以关系模型为基础的数据库,是目前最成熟、应用最广泛的数据库。本节以如图2.6所示的一个简化的“e学习”系统数据库为例讲解关系数据库的有关概念。
2.2.1 关系数据结构
1.表结构
关系表结构涉及以下概念。
(1)表。关系模型的数据结构单一,它采用二维表结构来表示实体及实体之间的联系。一个关系对应一个二维表,也可称为关系表,简称为表,例如,学生表、课程表等。
(2)属性。表中每列描述实体的一个特征,称为属性(也称字段或列)。每个属性都有相应的取值范围,称为值域。例如,学生表中的“姓名”取值为长度不大于16的字符串。
(3)记录。表中的每行由一个实体成员的属性取值构成,称为记录(或元组)。例如,学生表中的(1102,王洋,男,1999-11-09)是一条记录,它完整地描述了一个实体成员。记录中的一个属性值称为分量。例如,“王洋”是一个分量。
需要注意的是,关系是二维表,但这种表有以下限制。
① 表中的每个属性必须有唯一的名字,属性在表中的顺序可以任意交换。
【例2.1】通讯录表中多个联系电话的正确描述。
在图2.7(a)中,每个学生可有两个联系电话,但属性名相同是不合法的。修改两个属性名分别为“手机电话”和“座机电话”,如图2.7(b)所示。另外,属性的位置可随意调换。例如,可以将“姓名”移到最后一列。
图2.7 通讯录表
② 表中每个属性的取值都是基本数据类型,例如,整型、实型、字符型等,数组或结构等不能作为属性的类型。属性必须在所规定的值域内取值,不同属性的值域可以相同。
【例2.2】学生表中性别和出生日期的取值。
图2.8(a)中,如果规定“性别”字段的值域为一个字符,那么第二条记录的取值Male是不合法的;如果规定“出生日期”字段为日期型,那么,第二条记录的取值“1999年”是字符串,也是不合法的。图2.8(b)中各数据取值合法,其中的“出生日期”和“注册日期”字段的值域都是日期类型。
图2.8 学生表
③ 表中任意两条记录不能完全相同,即不允许有重复的行。记录在表中的顺序可以交换。
【例2.3】学生表中的重复记录。
在图2.9(a)中,第一条和第三条记录完全相同,这是不合法的。在图2.9(b)中,第一条和第二条记录虽然多数字段值相同,但学号值不同,这是合法的。另外,记录的顺序可以交换,这里将第二条记录移到最后也是可以的。
图2.9 学生表
(4)主键,也称主关键字(Primary Key)。主键是保证表中记录具有唯一性的一种机制。
① 候选码,也称候选关键字(Candidate Key),是关系表中按语义能唯一标识记录的最小属性的集合。在最简单的情况下,候选码只包含一个属性。在极端情况下,关系表的所有属性的集合是这个关系表的候选码,称为全码。
② 主键,用来指定在关系表中唯一标识记录的一个候选码。一个关系表可能有多个候选码,但只能选定其中一个为主键。主键的值不能为空且不能重复。
在一般情况下,为每个关系表都要定义主键,以保证任意两行数据记录不完全相同。
【例2.4】学生表的主键。
对于学生表,如果不允许表中出现姓名相同的学生,则该表中“学号”和“姓名”都具有唯一性语义,都是候选码,主键可以选定“学号”或“姓名”;如果允许表中出现姓名相同的学生,则“姓名”不能作为候选码,主键只能是“学号”。
主键应根据语义定义,可以是一个属性,也可以是多个属性组成的属性组。
【例2.5】选课表的主键。
选课表存放所有学生选修所有课程的信息。如果将“学号”定义为主键,那么每个学号只能在表中出现一次,即:每个学生只能选修一门课程,这显然与实际选课情况不符合。同理,“课程号”和“学分”都不适合作为主键。这时可以定义一组属性来作为主键,选择(学号,课程号)很合适。由此例可以看出,主键应根据现实世界中实体的实际情况确定。
2.表之间的关系
现实世界中的事物是相互联系的,这种联系需要通过数据模型体现出来。联系可以分为两种:一种是实体内部的联系,它反映了不同属性之间的联系,这种联系已经在表的结构中体现出来;另一种是实体之间的联系,在概念模型中采用E-R图描述,反映到关系模型中就是表和表之间的关系。
在关系模型中,表和表之间的关系通过表的公共属性来实现。在图2.6中,尽管学科数据与课程数据分别存放在不同的表中,但是通过学科表和课程表中的公共属性“学科号”就可以建立两个表之间的关联。例如,要查询有哪些“文学”类的课程,可以先从学科表中查出它的学科号是S07,然后根据学科号S07在课程表中查出对应的所有课程。反之,要查询“唐诗经典”课程属于哪个学科,也可以通过它的学科号在学科表中查询到“文学”。
两个表的公共属性之间的关联定义实现了两个表的连接运算,它不仅支持对数据库的多表连接数据操作,而且可以实现相关联数据表中数据的互相约束,从而保证数据的完整性,并减少数据冗余。因此,在设计数据库时,可以把复杂的事物分解,用多个表进行描述,利用表之间的关系使信息仍保持整体的逻辑结构。
为了描述表之间的关系,关系数据模型使用了外关键字、主表和外表等概念。
(1)外关键字(Foreign Key),简称外键。如果一个表中的主键与另一个表中的某个属性相同或相容(数据类型相同、语义相同、描述实体相同),可使用这个相同或相容的公共属性建立两个表之间的联系,这个起联系作用的属性在另一个表中被称为外键。
提示:公共属性在两个表中名称可以不同。但为了设计和开发方便,在数据库设计时,最好为不同表中的公共属性定义相同的属性名。
(2)主表和外表。当两个表关联后,两个表就有了角色之分。公共属性作为主键的表称为主表,另一个表称为外表。
分析以上定义,可以得到在两个表之间建立关系的一般原则:
① 两个表具有能体现实体存在联系的相同或相容的公共属性;
② 该公共属性至少在其中一个表中是主键。
图2.6中用连线指示了各个表之间的关系,连线箭头指向主表,主表中用于建立关系的属性是主键;连线另一端是外表,外表中用于建立关系的属性是外键。下面通过几个小例子详细说明如何通过外键定义表之间的关系。
【例2.6】学科表和课程表之间的一对多关系。
学科实体和课程实体存在归属关系,一个学科开设多门课程,任何一门课程都属于且仅属于某个学科。学科表和课程表有相同属性“学科号”,可以用“学科号”建立二者之间一对多的关系(见图2.10),在学科表中的“学科号”是主键,而在课程表中的“学科号”就是外键。在这个关系中,学科表是主表,课程表是外表。
图2.10 学科表和课程表之间的一对多关系
提示:当建立关系的公共属性只是其中一个表的主键时,建立的是一对多关系。
【例2.7】学生表和毕业证表之间的一对一关系。
学生实体和毕业证实体存在获得关系,可以用它们的共同属性“学号”建立关系。“学号”作为主键所在的学生表是主表,毕业证表是外表,如图2.11(a)所示。为保证这是一对一关系,需要在外表(毕业证表)中限定“学号”取值唯一,可通过为“学号”字段建立唯一索引实现。
还可以采用另外一种设计方案,如图2.11(b)所示:将“学号”也设为毕业证表的主键,利用它们的共同属性“学号”建立在学生表和毕业证表之间的一对一关系。在这个由两个主键建立的关系中,哪个是主表,哪个是外表呢?理论上,可以任选一个作为主表,另一个作为外表。但在关系中,主表约束外表,要根据实际的关系分析,选择一般性、主导性信息所在的表作为主表。因此,在该关系中,定义学生表为主表,毕业证表为外表。这样,毕业证表中的“学号”既是该表的主键,也是用于关联学生表的外键。
提示:当建立关系的公共属性在一个表中是主键,在另一个表中也是主键或唯一索引时,建立的是一对一关系。
图2.11 学生表和毕业证表之间的一对一关系
【例2.8】教师表和课程表之间的一对多关系。
教师实体和课程实体之间存在讲授关系(见图2.6)。它们没有名字相同的属性,但教师表中的属性“工号”和课程表中的属性“教师工号”,数据类型和含义相同,且“工号”在教师表中是主键,可以用这对属性建立一个一对多关系,教师表是主表,课程表是外表。
【例2.9】学生表和教师表之间的关系。
教师实体和学生实体之间可能存在多种关系,如任课、指导等。但在图2.6的各个表中,没有体现这种关系的公共属性。虽然学生表和教师表都有属性“姓名”和“性别”,但是它们分别描述不同的实体,并不是公共属性。如果需要表达以上某种师生关系,则可以选择以下设计。
① 任课关系。图2.6可以表达任课关系,不需要额外设计,因为通过学生表和选课表、选课表和课程表、课程表和教师表之间的关系,可以找到任课教师信息。
② 指导关系。可以在学生表中增加一个属性“工号”,用来记录该学生的指导教师,然后利用“工号”来建立教师表和学生表之间的一对多关系。
从图2.6可以看出,尽管数据库中的各个表是独立的,但是表与表之间可以通过外键建立相互联系,从而构成一个整体的逻辑结构。而且除了外键和一些必需的属性,这些表中尽可能地减少了数据冗余。
3.关系模式
表中的行定义(即表头)是实体所有相关属性的集合,称为该表的关系模式,通常记为:
为一个数据库定义的所有关系模式的集合构成该关系数据库的逻辑结构模型。“e学习”系统数据库由9个关系模式构成(见图2.12),其中带下画线的属性为主键,带星号(*)的属性是外键。
图2.12 “e学习”系统数据库的关系模型
关系模式确定后,在数据库物理设计阶段可以用表格详细地描述关系模式的定义。
【例2.10】选课表关系模式的物理结构设计。
图2.13采用表格描述选课表关系模式的物理结构设计,包括属性名称、属性说明、类型定义、属性限定和关系(外键)。“学号”的类型是长度为4的整数,“课程号”是长度为4的字符串,“成绩”是总长为5且保留1位小数的数值型。该表的主键为(学号,课程号)。该表通过“学号”与学生表建立关系,是学生表的外表;该表通过“课程号”与课程表建立关系,是课程表的外表。
图2.13 选课表关系模式的物理结构设计
除了用表格详细描述关系模式,还可以用关系数据库的结构化查询语言(Structured Query Language,SQL)中的数据定义语句来定义关系模式(参见4.1.2节),数据库管理系统执行这些描述命令后就可以在数据库中建立数据表对象。
4.E-R图向关系模型转换
关系模型的逻辑结构是一组关系模式的集合。将我们前面建立起来的概念模型E-R图进行转换就可以得到这些关系模式,即:将E-R图中的实体及实体间的联系转换为关系模式,并确定这些关系模式的属性和主键。主要转换规则如下。
(1)实体到关系模式的转换。一般来说,E-R图中的一个实体转换为一个关系模式,实体名就是关系名,实体的属性就是关系模式的属性,实体的关键字就是关系模式的主键。
(2)联系到关系模式的转换。联系可以单独转换为一个关系模式,但根据联系类型不同,通常采用以下不同的转换规则。
① 一对一联系的属性与一个实体的主键一起合并到另一个实体对应的关系模式中。
【例2.11】“学生”和“毕业证”实体之间联系的转换。
图2.2(a)中的E-R图可转换为两个关系模式,有两种方案(见图2.14)。
图2.14 一对一联系转换为关系模式
分析可知,方案2优于方案1。因为毕业生只占学生的一部分,方案1中学生关系模式的“证书号”和“发证时间”数据项有一部分为空,浪费存储空间。进一步分析方案2中的毕业证关系模式,可以选择“学号”和“证书号”中的一个作为主键,另一个建立唯一索引,保证其唯一性。这里我们选择“证书号”作为主键。
② 一对多联系的属性与一端实体的主键一起合并到多端实体所对应的关系模式中。
【例2.12】“课程”和“课件”实体之间联系的转换方法。
图2.2(b)中的E-R图转换为两个关系模式“课程”和“课件”(见图2.15)。
图2.15 一对多联系转换为关系模式
③ 一个多对多联系必须转换为一个独立的关系模式。该关系模式的属性包括联系本身的属性及两端实体的主键,其主键由两个实体的主键构成。
【例2.13】“学生”和“课程”实体之间联系的转换方法。
图2.2(c)中的E-R图转换为三个关系模式“学生”“课程”和“选课”(见图2.16)。
图2.16 一对一联系转换为关系模式
④ 三个或三个以上实体间的一个多元联系可以转化为一个关系模式。与该多元联系相连的各个实体的主键及联系本身的属性均转换为此关系模式的属性,而此关系模式的主键包含各个实体的主键。
⑤ 具有相同主键的关系模式可以合并,但是否合并取决于实际设计需求。
2.2.2 关系操作
关系数据结构描述了关系模型的静态特性,实现了信息的结构化存储。关系操作则说明了其动态特性,描述关系模型中的数据允许执行的操作及其操作规则的集合,实现了数据访问支持。
关系操作以关系代数为理论基础。关系表可以看作记录的集合。传统的集合操作包括并、交、差、笛卡儿积等,这些集合操作对应数据库针对行的基本操作。另外,关系模型还专门定义了针对列的操作,包括选择、投影、连接等。上述所有操作的结果仍然是记录的集合,即关系表。本书将在2.3.2节中介绍关系操作的有关理论基础。
根据关系模型支持的各种操作运算,关系数据库主要支持以下针对关系表的操作。
① 插入。在一个表中插入一条或多条新记录。
② 删除。从一个表删除一条或多条满足条件的记录。
③ 修改。在一个表中修改满足条件的记录的某些字段的值。
④ 查找。从一个或多个表中提取满足条件的数据记录,生成计算列或汇总数据。
关系数据库的基本操作语言是SQL,它以简洁的语法支持上述各类操作。本书将在第4章中详细讲解SQL语言。
2.2.3 关系完整性约束
对关系表进行关系操作可能会使表中的数据发生变化。关系完整性约束是对关系模型中的数据取值及数据取值变化时的制约关系的描述,用于保证关系操作后表中的数据仍能有效地反映所描述实体的实际状态,保证多个表中相关数据的一致。
完整性约束规则是在表和属性上定义的约束条件。数据库管理系统依据这些约束条件对数据取值进行检查,使不合法数据不能进入数据库。关系模型的完整性约束规则主要包括域完整性规则、实体完整性规则和参照完整性规则。
1.域完整性规则
域完整性规则规定:属性的取值必须是属性值域中的值。
域完整性规则是针对属性实施的。它在关系模型定义时,对属性的数据类型、长度、单位、精度、格式、值域、是否允许为“空值”等进行限定。
【例2.14】学生表的域完整性规则应用。
对学生表进行物理结构设计,根据实际情况定义各字段的属性(见图2.17)。
类型定义限定了属性的取值类型:“学号”是长度为4的整数,“姓名”是长度不超过16的可变字符串,“性别”是长度为1的定长字符串,“出生日期”是日期型数据。
属性取值的值域也可以限定。例如,“姓名”和“性别”不允许为空值(记为“Not Null”),“性别”的默认值是“男”,“出生日期”的值应“>=1990-01-01”等。
图2.17 学生表的域完整性规则应用
提示:空值表示“不知道”或“未定义”。数值零、空字符或空字符串都不是空值。例如,没有成绩与成绩为零分显然是不同的。“允许空”表示该属性可以不填写任何值,“不允许为空”要求任何记录在该属性处必须有值。默认值表示如果该字段不输入值,则自动填入该值。
应根据实体特点和应用语义进行属性限定,建立域完整性规则。
2.实体完整性规则
实体完整性规则规定:主键的取值不能为空且不能重复。
实体完整性规则是针对关系表而言的,目的是保证表中记录的唯一性。如果表中定义了主键,关系数据库管理系统就会强制检查数据以保证实体完整性。
【例2.15】学生表的实体完整性规则应用。
按照图2.17(a)对学生表关系模式的定义,“学号”是主键,那么图2.17(b)中的数据符合实体完整性规则。假定有一条新记录(1103,王秋水,女,2000-03-04)需要插入学生表,系统会拒绝该请求,因为它违反了实体完整性规则,表中已存在一条主键值为1103的记录。
3.参照完整性规则
参照完整性规则规定:表的外键的取值必须是其对应的主表中主键的已有值或空值。
因为数据库的表之间存在关联关系,而且有些属性在多个表中重复出现,所以,为了保证数据完整性,需要对表之间重复出现的数据进行约束。参照完整性是在表间关系的基础上实施的表之间的数据约束。
【例2.16】学科表和课程表之间的参照完整性规则应用。
如图2.10所示,学科表和课程表之间建立了一对多的关系,课程表中的“学科号”是外键。如果在这个关系上实施参照完整性约束,那么课程表中“学科号”的取值必须是空值或在学科表中“学科号”属性出现过的值。也就是说,先有学科再有学科下的课程,如果课程表的“学科号”属性取值允许为空,则表示该课程还没有确定属于哪个学科。
对数据表进行更新操作时,可能会破坏表之间的参照完整性。数据库管理系统支持进一步根据操作类型设置限制细节,这些限制包括插入约束、删除约束和更新约束。
(1)插入约束。设置插入约束,可以在外表中插入新记录时,要求外键值在主表中已存在或为空值(如果允许为空)。
例如,向图2.10所示的课程表中添加一条记录(C065,明史,2,T001,S11),操作会被拒绝,因为学科表中不存在S11学科,该记录违反了参照完整性规则。
(2)删除约束。设置删除约束,可以保证在从主表中删除记录时保持外表数据的完整性。删除约束有两种。一种是限制删除,即:如果要删除记录的主键值在某个外表中存在,则不允许删除;另一种是级联删除,即:在删除主表中记录之前,将外表中外键值与之匹配的记录全部删除。
例如,从图2.10所示的学科表中删除学科号为S06的记录,系统会检查课程表,发现有相关的“线性代数”等课程。如果设置了限制删除,则系统会拒绝删除操作,以免这些相关课程失去所属学科的信息。如果设置了级联删除,则系统会在删除学科表记录的同时,将课程表中所有学科号是S06的记录全部删除。
(3)更新约束。设置更新约束,可以保证在修改主表中的主键值时保持外表数据的一致性。更新约束有两种。一种是限制更新,即:如果要更新记录的主键的取值在某个外表中存在,则不允许更新。另一种是级联更新,即:在更新主表中主键之后,将外表中与之匹配的外键值全部更新。
例如,将图2.10所示的学科表中学科号S06修改为S88,系统检查课程表发现有相关的“线性代数”等课程。如果设置了限制更新,则系统会拒绝更新操作;如果设置了级联更新,则系统会在修改学科表的同时,将课程表中所有学科号是S06的课程的学科号全部改为S88。
提示:本例中S88必须是学科表中不存在的学科号,否则违反实体完整性规则。
通过以上例子可以发现,保证数据的完整性和一致性对数据库是至关重要的。在数据库设计时,必须充分考虑并建立关系完整性约束规则。关系完整性约束规则的用途主要体现在以下三个方面。
① 保证数据的有效、完整和一致,避免给应用带来困难或错误。
② 减少不合法的垃圾数据在数据库中的堆积,保证数据质量。
③ 简化应用程序开发,减轻输入有效性检查的负担,有些数据还可以通过级联操作由数据库管理系统自动维护。
关系数据库管理系统提供了比较完善的约束机制。只要在定义表结构时考虑域完整性和实体完整性,并且在建立表之间的关系后进行参照完整性约束方式的设置,关系数据库管理系统就会根据这些规则来自动实施关系完整性约束。