赵亮《数据库系统概论》

王珊《数据库系统概论》

主讲教师:赵亮

第1章 绪论

1.1 数据库系统概述

1.1.1 数据、数据库、数据库管理系统、数据库系统

一、数据(Data) 数据是数据库中存储的基本对象。描述事物的符号记录称为数据。描述事物的符号可以是数字,也可以是文字、图形、图像、声音、语言等,数据有多种表现形式,它们都可以经过数字化后存入计算机。

二、数据库(DataBase,简称DB) 数据库是长期储存在计算机内、有组织的、可共享的大量数据的集合。数据库数据具有永久存储、有组织和可共享三个基本特点。

三、数据库管理系统(DataBase Management System,DBMS) 数据库管理系统的主要功能包括:

  1. 数据定义功能:DBMS提供数据定义语言(Data Definition Language,DDL),用户通过它可以方便地对数据库中的数据对象进行定义。

  2. 数据组织、存储和管理:DBMS要分类组织、存储和管理各种数据,包括数据字典、用户数据、数据的存取路径等。

  3. 数据操纵功能:DBMS提供数据操纵语言(Data Manipulation Language,DML),用户可以使用DML操纵数据,实现对数据库的基本操作,如查询、插入、删除和修改等。

  4. 数据库的事务管理和运行管理:数据库在建立、运用和维护时由数据库管理系统统一管理、统一控制,以保证数据的安全性、完整性、多用户对数据的并发使用及发生故障后的系统恢复。

  5. 数据库的建立和维护功能:数据库初始数据的输入、转换功能,数据库的转储、恢复功能,数据库的重组织功能和性能监视、分析功能等。

四、数据库系统(DataBase System,DBS) 数据库系统一般由数据库、数据库管理系统(及其开发工具)、应用系统、数据库管理员构成。数据库系统在整个计算机系统中的地位如下:

1.1.2 数据管理技术的产生和发展

数据管理技术经历了人工管理、文件系统、数据库系统3个阶段。

一、人工管理阶段 人工管理数据具有如下特点: (1)数据不保存; (2)应用程序管理数据; (3)数据不共享; (4)数据不具有独立性。 缺点:数据的逻辑结构或物理结构发生变化后,必须对应用程序做相应的修改,这就加重了程序员的负担。

二、文件系统阶段 用文件系统管理数据具有如下特点: (1)数据可以长期保存; (2)由文件系统管理数据。 缺点: (1)数据共享性差,冗余度大; (2)数据独立性差。

三、数据库系统阶段 用数据库系统管理数据具有如下特点: (1)数据结构化; (2)数据的共享性高,冗余度低,易扩充; (3)数据独立性高; (4)数据由DBMS统一管理和控制;

这3个阶段的特点及其比较如下表:

1.2 数据模型

数据模型(Data Model)也是一种模型,它是对现实世界数据特征的抽象。数据模型就是现实世界的模拟。

1.2.1 两类数据模型

数据模型应满足三方面要求: ①能比较真实地模拟现实世界; ②容易为人所理解; ③便于在计算机上实现。

根据模型应用的不同目的,可分为两类: 第一类是概念模型(Conceptual Model)。 概念模型也称信息模型,它是按用户的观点来对数据和信息建模,主要用于数据库设计。

第二类是逻辑模型和物理模型。 ①逻辑模型主要包括层次模型(Hierarchical Model)、网状模型(Network Model)、关系模型(Relational Model)、面向对象模型(Object Oriented Model)和对象关系模型(Object Relational Model)等。它是按计算机系统的观点对数据建模,主要用于DBMS的实现。 ②物理模型是对数据最低层的抽象,它描述数据在系统内部的表示方式和存取方法,在磁盘或磁带上的存储方式和存取方法,是面向计算机系统的。

1.2.2 数据模型的组成要素

数据模型通常由 数据结构、数据操作和完整性约束 三部分组成。

一、数据结构 数据结构描述数据库的组成对象以及对象之间的联系。数据结构是所描述的对象类型的集合,是对系统静态特性的描述。

二、数据操作 数据库主要有查询和更新(包括插入、删除、修改)两大类操作。数据操作是对系统动态特性的描述。

三、数据的完整性约束条件 数据的完整性约束条件是一组完整性规则。 【例】在关系模型中,任何关系必须满足实体完整性和参照完整性两个条件。 【例】在某大学的数据库中规定教授的退休年龄是65周岁,男职工的退休年龄是60周岁,女职工的退休年龄是55周岁等。

1.2.3 概念模型

概念模型是现实世界到机器世界的一个中间层次,表现为: ①概念模型用于信息世界的建模; ②现实世界到信息世界的第一层抽象; ③数据库设计人员进行数据库设计的有力工具; ④数据库设计人员和用户之间进行交流的语言。 概念模型要求: ①具有较强的语义表达能力; ②能够方便、直接地表达应用中的各种语义知识; ③简单、清晰、易于用户理解。

一、信息世界中的基本概念

  1. 实体(Entity) 客观存在并可相互区别的事物称为实体。实体可以是具体的人、事、物,也可以是抽象的概念或联系。 【例】一个职工、一个学生、一个部门、一门课、学生的一次选课等都是实体。

  2. 属性(Attribute) 实体所具有的某一特性称为属性。一个实体可以由若干个属性来刻画。 【例】学生实体可以由学号、姓名、性别、出生年月、所在院系、入学时间等属性组成。(94002268,张三,男,197605,计算机系,1994)这些属性组合起来表征了一个学生。

  3. 码(Key) 唯一标识实体的属性集称为码。 【例】学号是学生实体的码。

  4. 域(Domain) 域是一组具有相同数据类型的值的集合。属性的取值范围来自某个域。 【例】学号的域为8位整数,学生年龄的域为整数,性别的域为(男,女)。

  5. 实体型(Entity Type) 具有相同属性的实体必然具有共同的特征和性质。用实体名及其属性名集合来抽象和刻画同类实体,称为实体型。 【例】学生(学号,姓名,性别,出生年月,所在院系,入学时间)就是一个实体型。

  6. 实体集(Entity Set) 同一类型实体的集合称为实体集。 【例】全体学生就是一个实体集。

  7. 联系(Relationship) 在现实世界中,事物内部以及事物之间是有联系的,这些联系在信息世界中反映为实体(型)内部的联系和实体(型)之间的联系。 实体内部的联系通常是指组成实体的各属性之间的联系;实体之间的联系通常是指不同实体集之间的联系。

二、两个实体型之间的联系

  1. 一对一联系(1:1) 如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之联系,反之亦然,则称实体集A与实体集B具有一对一联系,记为1:1。 【例】学校里面,一个班级只有一个正班长,而一个班长只在一个班中任职,则班级与班长之间具有一对一联系。

  2. 一对多联系(1:n) 如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系,反之,对于实体集B中的每一个实体,实体集A中至多只有一个实体与之联系,则称实体集A与实体集B有一对多联系,记为1:n。 【例】一个班级中有若干名学生,而每个学生只在一个班级中学习,则班级与学生之间具有一对多联系。

  3. 多对多联系(m:n) 如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系,反之,对于实体集B中的每一个实体,实体集A中也有m个实体(m≥0)与之联系,则称实体集A与实体集B具有多对多联系,记为m:n。 【说明】实际上,一对一联系是一对多联系的特例,而一对多联系又是多对多联系的特例。 【例】一门课程同时有若干个学生选修,而一个学生可以同时选修多门课程,则课程里学生之间具有多对多联系。

三、两个以上的实体型之间的联系 两个以上的实体型之间也存在着一对一、一对多、多对多联系。 若实体型E1,E2,…,En之间存在联系,对于实体型Ei(j=1,2,…,i-1,i+1,…,n)中的给定实体,最多只和Ei中的一个实体相联系,则说Ei与E1,E2,…,Ei-1,Ei+1,…,En之间能联系是一对多的。 【例】对于课程、教师与参考书3个实体型,如果一门课程可以有若干个教师讲授,使用若干本参考书,而每一个教师只讲授一门课程,每一本参考书只供一门课程使用,则课程与教师、参考书之间的联系是一对多的。

【例】有3个实体型:供应商、项目、零件,一个供应商可以供给多个项目多种零件,而每个项目可以使用多个供应商供应的零件,每种零件可由不同供应商供给,由此看出供应商、项目、零件三者之间是多对多的联系。

四、单个实体型内的联系 同一个实体集内的各实体之间也可以存在一对一、一对多、多对多的联系。 【例】职工实体型内部具有领导与被领导的联系,即某一职工(干部)“领导”若干名职工,而一个职工仅被另外一个职工直接领导,因此这是一对多的联系。

五、概念模型的一种表示方法:实体-联系图(E-R图) E-R图提供了表示实体型、属性和联系的方法。 实体型:用矩形表示,矩形框内写明实体名。 属性:用椭圆形表示,并用无向边将其与相应的实体型连接起来。 【例】学生实体具有学号、姓名、性别、出生年份、系、入学时间等属性。 联系:用菱形表示,菱形框内写明联系名,并用无向边分别与有关实体型连接起来,同时在无向边旁标上联系的类型(1:1,1:n或m:n)。 【注意】如果一个联系具有属性,则这些属性也要用无向边与该联系连接起来。 【例】如果用“供应量”来描述联系“供应”的属性,表示某供应商供应了多少数量的零件给某个项目。那么这3个实体及其之间联系的E-R图如下。

六、一个实例 用E-R图来表示某个工厂物资管理的概念模型。 物资管理涉及的实体有: ①仓库属性有仓库号、面积、电话号码; ②零件属性有零件号、名称、规格、单价、描述; ③供应商属性有供应商号、姓名、地址、电话号码、账号; ④项目属性有项目号、预算、开工日期; ⑤职工属性有职工号、姓名、年龄、职称。

实体之间的联系如下: (1)一个仓库可以存放多种零件,一种零件可以存放在多个仓库中,因此仓库和零件具有多对多的联系。用库存量来表示某种零件在某个仓库中的数量。 (2)一个仓库有多个职工当仓库保管员,一个职工只能在一个仓库工作,因此仓库和职工之间是一对多的联系。 (3)职工之间具有领导-被领导关系。即仓库主任领导若干保管员,因此职工实体集中具有一对多的联系。 (4)供应商、项目和零件三者之间具有多对多的联系。即一个供应商可以供给若干项目多种零件,每个项目可以使用不同供应商供应的零件,每种零件可由不同供应商供给。

实体及属性的E-R图: 实体及其联系的E-R图: 完整的E-R图:

1.2.4 最常用的数据模型

目前,数据库领域中最常用的逻辑数据模型有:层次模型(Hierarchical Model)、网状模型(Network Model)、关系模型(Relational Model)、面向对象模型(Object Oriented Model)、对象关系模型(Object Relational Model)。

1.2.5 关系模型

一、关系数据模型的数据结构 关系(Relation):一个关系对应通常说的一张表,如下表中的这张学生登记表; 元组(Tuple):表中的一行即为一个元组; 属性(Attribute):表中的一列即为一个属性,给每一个属性起一个名称即属性名。 【例】下表有6列,对应6个属性(学号,姓名,年龄,性别,系名和年级)

码(Key):也称为码键。表中的某个属性组,它可以唯一确定一个元组;如上表中的学号,可以惟一确定一个学生,也就成为本关系的码; 域(Domain):属性的取值范围,如人的年龄一般在1~150岁之间; 分量:元组中的一个属性值; 关系模式:对关系的描述,一般表示为:关系名(属性1,属性2,…,属性n)。 【例】上面的关系可描述为:学生(学号,姓名,年龄,性别,系名,年级) 【例】学生、课程、学生与课程之间的多对多联系在关系模型中可以如下表示: 学生(学号,姓名,年龄,性别,系名,年级) 课程(课程号,课程名,学分) 选修(学号,课程号,成绩)

二、关系数据模型的操纵与完整性约束 关系数据模型的操作主要包括查询、插入、删除和更新数据。这些操作必须满足关系的完整性约束条件。 关系的完整性约束条件包括三大类: ①实体完整性; ②参照完整性; ③用户定义的完整性。

三、关系数据模型的优点

  1. 关系模型与格式化模型不同,它是建立在严格的数学概念的基础上的。

  2. 关系模型的概念单一。

  3. 关系模型的存取路径对用户透明,从而具有更高的数据独立性、更好的安全保密性也简化了程序员的工作和数据库开发建立的工作。

1.3 数据库系统结构

1.3.1 数据库系统模式的概念

模式(Schema)是数据库中全体数据的逻辑结构和特征的描述,同一个模式可以有很多实例。 【例】在学生选课数据库模式中,包含学生记录、课程记录和学生选课记录,则2003年有一个学生数据库的实例,该实例包含了2003年学校中所有学生的记录(如果某校有10000个学生,则有10000个学生记录)、学校开设的所有课程的记录和所有学生选课的记录。

1.3.2 数据库系统的三级模式结构

数据库系统的三级模式结构是指数据库系统是由外模式、模式和内模式三级构成。

一、模式(Schema) 模式也称逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。它是数据库系统模式结构的中间层,既不涉及数据的物理存储细节和硬件环境,也与具体的应用程序、所使用的应用开发工具及高级程序设计语言(如C,COBOL,FORTRAN)无关。

二、外模式(External Schema) 外模式也称子模式(Subschema)或用户模式,它是数据库用户(包括应用程序员和最终用户)能够看见和使用的局部数据的逻辑结构和特征的描述,是数据库用户的数据视图,是与某一应用有关的数据的逻辑表示。 【注意】

  1. 外模式通常是模式的子集,一个数据库可以有多个外模式。

  2. 同一外模式也可以为某一用户的多个应用系统所使用,但一个应用程序只能使用一个外模式。

  3. 外模式是保证数据库安全性的一个有力措施。每个用户只能看见和访问所对应的外模式中的数据,数据库中的其余数据是不可见的。

三、内模式(Internal Schema) 内模式也称存储模式(Storage Schema),一个数据库只有一个内模式。它是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。

1.3.3 数据库的二级映像功能与数据独立性

数据库系统的三级模式是对数据的3个抽象级别,它把数据的具体组织留给DBMS管理,使用户能逻辑地抽象地处理数据,而不必关心数据在计算机中的具体表示方式与存储方式。数据库管理系统在这三级模式之间提供了两层映像: 外模式/模式映像 模式/内模式映像 两层映像保证了数据库系统中的数据能够具有较高的逻辑独立性和物理独立性。

一、外模式/模式映像 模式描述的是数据的全局逻辑结构,外模式描述的是数据的局部逻辑结构。当模式改变时,由数据库管理员对各个外模式/模式的映像作相应改变,可以使外模式保持不变。应用程序是依据数据的外模式编写的,从而应用程序不必修改,保证了数据与程序的逻辑独立性,简称数据的逻辑独立性。

二、模式/内模式映像 数据库中只有一个模式,也只有一个内模式,所以模式/内模式映像是唯一的,它定义了数据全局逻辑结构与存储结构之间的对应关系。 【例】当数据库的存储结构改变了(例如选用了另一种存储结构),由数据库管理员对模式/内模式映像作相应改变,可以使模式保持不变,从而应用程序也不必改变。保证了数据与程序的物理独立性,简称数据的物理独立性。

1.4 数据库系统的组成

数据库系统一般由数据库、数据库管理系统(及其开发工具)、应用系统和数据库管理员构成。

一、硬件平台及数据库

硬件资源要求: (1)要有足够大的内存,存放操作系统、DBMS的核心模块、数据缓冲区和应用程序; (2)有足够的大的磁盘或磁盘阵列等设备存放数据库,有足够的磁带(或光盘)作数据备份; (3)要求系统有较高的通道能力,以提高数据传送率。

二、软件

数据库系统的软件主要包括: (1)DBMS。DBMS是为数据库的建立、使用和维护配置的系统软件。 (2)支持DBMS运行的操作系统。 (3)具有与数据库接口的高级语言及编译系统,便于开发应用程序。 (4)以DBMS为核心的应用开发工具。 (5)为特定应用环境开发的数据库应用系统。

三、人员

1. 数据库管理员(DataBase Administrator,DBA) 需要有专门的管理机构来监督和管理数据库系统。DBA则是这个机构的一个(组)人员,负责全面管理和控制数据库系统。具体职责包括: (1)决定数据库中的信息内容和结构,数据库中要存放哪些信息,DBA要参与决策; (2)决定数据库的存储结构和存取策略; (3)定义数据的安全性要求和完整性约束条件; (4)监控数据库的使用和运行; (5)数据库的改进和重组重构。

2. 系统分析员和数据库设计人员 系统分析员负责应用系统的需求分析和规范说明,要和用户及DBA相结合,确定系统的硬件软件配置,并参与数据库系统的概要设计。 数据库设计人员负责数据库中数据的确定、数据库各级模式的设计。

3. 应用程序员 应用程序员负责设计和编写应用系统的程序模块,并进行调试和安装。

4. 用户 这里用户是指最终用户(End User)。最终用户通过应用系统的用户接口使用数据库。

第2章 关系数据库

关系数据库简介

  • 1970年IBM公司的E.F.Codd提出关系数据模型。

  • 1972年提出了关系的第一、第二、第三范式。

  • 1974年提出了关系的BC范式。

  • 80年代后,关系数据库系统成为最重要、最流行的数据库系统。

  • 典型实验系统:System R、University INGRES。

  • 典型商用系统:ORACLE、DB2、SYBASE、INGRES、INFORMIX。

2.1 关系数据结构及形式化定义

2.1.1 关系

  • 单一的数据结构——关系:现实世界的实体以及实体间的各种联系均用关系来表示。

  • 逻辑结构——二维表:从用户角度,关系模型中数据的逻辑结构是一张二维表,关系模型是建立在集合代数的基础上。

  • 域(Domain):域是一组具有相同数据类型的值的集合。例如:整数、实数、介于某个取值范围的整数、指定长度的字符串集合、{“男”,“女”}等。

  • 笛卡尔积(Cartesian Product):给定一组域D1,D2,…,Dn,这些域可以是相同的。D1,D2,…,Dn的笛卡尔积为:D1×D2×…×Dn={(d1,d2,…,dn)|di∈Di,i=1,2,…,n}。所有域的所有取值的一个组合。

  • 元组(Tuple):笛卡尔积中每一个元素(d1,d2,…,dn)称作一个n元组(n-tuple)或简称元组(Tuple)。例如:(张清玫,计算机专业,李勇)。

  • 分量(Component):笛卡尔积元素(d1,d2,…,dn)中的每一个值di称作一个分量。例如:张清玫、计算机专业、李勇等。

  • 基数(Cardinal number):若Di(i=1,2,…,n)为有限集,其基数为mi(i=1,2,…,n),则D1×D2×…×Dn的基数M为:。

  • 关系(Relation)

    • D1×D2×…×Dn的子集称做在域D1,D2,…,Dn上的关系,表示为R(D1,D2,…,Dn)。R表示关系名,n表示关系的目或度(Degree)。

    • 关系中的每个元素是关系中的元组,通常用t表示。

    • 当n=1时,称该关系为单元关系(Unary relation)或一元关系;当n=2时,称该关系为二元关系(Binary relation)。

    • 关系也是一个二维表,表的每行对应一个元组,表的每列对应一个域、一个属性。

    • 关系中不同列可以对应相同的域,为了加以区分,必须对每列起一个名字,称为属性(Attribute)。n目关系必有n个属性。

    • 候选码(Candidate key):若关系中的某一属性组的值能唯一地标识一个元组,则称该属性组为候选码。简单的情况:候选码只包含一个属性。全码(All-key):最极端的情况:关系模式的所有属性组是这个关系模式的候选码,称为全码(All-key)。主码:若一个关系有多个候选码,则选定其中一个为主码(Primary key)。主属性:候选码的诸属性称为主属性(Prime attribute)。非主属性:不包含在任何侯选码中的属性(Non-Prime attribute)或非码属性(Non-key attribute)。

    • 三类关系:

      • 基本关系(基本表或基表):实际存在的表,是实际存储数据的逻辑表示。

      • 查询表:查询结果对应的表。

      • 视图表:由基本表或其他视图表导出的表,是虚表,不对应实际存储的数据。

    • 基本关系的性质:

      • 列是同质的(Homogeneous)。

      • 不同的列可出自同一个域,其中的每一列称为一个属性,不同的属性要给予不同的属性名。

      • 列的顺序无所谓,列的次序可以任意交换。

      • 任意两个元组的候选码不能相同。

      • 行的顺序无所谓,行的次序可以任意交换。

      • 分量必须取原子值,这是规范条件中最基本的一条。

2.1.2 关系模式

  • 什么是关系模式:关系模式(Relation Schema)是对关系的描述。关系模式是型,关系是值。

    • 元组集合的结构:属性构成、属性来自的域、属性与域之间的映象关系。

    • 一个关系通常由赋予它的元组语义确定。

    • 现实的世界中还存在着完整性约束。

  • 定义关系模式:关系模式可以形式化地表示为:R(U,D,DOM,F)。R:关系名;U:组成该关系的属性名集合;D:属性组U中属性所来自的域;DOM:属性向域的映象集合;F:属性间的数据依赖关系集合。例如:导师和研究生出自同一个域—人,因此取不同的属性名,并在模式中定义属性向域的映象,即说明它们分别出自哪个域:DOM(SUPERVISOR-PERSON)=DOM(POSTGRADUATE-PERSON)=PERSON。

  • 关系模式与关系:关系模式是静态的、稳定的。关系是动态的、随时间不断变化的。关系是关系模式在某一时刻的状态或内容,在实际工作中关系模式和关系往往统称为关系,需要通过上下文加以区别。

2.1.3 关系数据库

  • 关系数据库:在一个给定的应用领域中,所有关系的集合构成一个关系数据库。

  • 关系数据库的型与值

    • 关系数据库的型:关系数据库模式,对关系数据库的描述。

    • 关系数据库模式:若干域的定义,在这些域上定义的若干关系模式。

    • 关系数据库的值:关系模式在某一时刻对应的关系的集合,简称为关系数据库。

2.1.4 关系模型的存储结构

  • 有的关系数据库管理系统中一个表对应一个操作系统文件,将物理数据组织交给操作系统完成。

  • 有的关系数据库管理系统从操作系统那里申请若干个大的文件,自己划分文件空间,组织表、索引等存储结构,并进行存储管理。

2.2 关系数据结构

2.2.1 基本关系操作

  • 常用的关系操作

    • 查询:选择、投影、连接、除、并、交、差等,其中选择、投影、并、差、笛卡尔积是5种基本操作。

    • 数据更新:插入、删除、修改。

    • 查询的表达能力是其中最主要的部分。

  • 关系操作的特点:集合操作方式,操作的对象和结果都是集合,一次一集合的方式。

2.2.2 关系数据库语言的分类

  • 关系代数语言:用对关系的运算来表达查询要求。代表:ISBL。

  • 关系演算语言:用谓词来表达查询要求。

    • 元组关系演算语言:谓词变元的基本对象是元组变量。代表:APLHA,QUEL。

    • 域关系演算语言:谓词变元的基本对象是域变量。代表:QBE。

  • 具有关系代数和关系演算双重特点的语言:代表:SQL(Structured Query Language)。

2.3 关系的完整性

  • 关系模型中有三类完整性约束:实体完整性、参照完整性和用户定义的完整性。其中实体完整性、参照完整性是关系模型必须满足的完整性约束条件,称为关系的两个不变性,应该由关系系统自动支持。用户定义的完整性是应用领域需要遵循的约束条件,体现了具体领域中的语义约束。

2.3.1 实体完整性

  • 实体完整性规则(Entity Integrity):若属性A是基本关系R的主属性,则属性A不能取空值。

    • 空值就是“不知道”或“不存在”或“无意义”的值。

    • 实体完整性规则的说明:

      • 实体完整性规则是针对基本关系而言的。一个基本表通常对应现实世界的一个实体集。

      • 现实世界中的实体是可区分的,即它们具有某种唯一性标识。

      • 关系模型中以主码作为唯一性标识。

      • 主码中的属性即主属性不能取空值。主属性取空值,就说明存在某个不可标识的实体,即存在不可区分的实体,这与实体的唯一性相矛盾,因此这个规则称为实体完整性。

    • 注意:实体完整性规则规定基本关系的所有主属性都不能取空值。例如:选修(学号,课程号,成绩),“学号、课程号”为主码,则学号和课程号两个属性都不能取空值。

2.3.2 参照完整性

  • 关系间的引用

    • 在关系模型中实体及实体间的联系都是用关系来描述的,存在着关系与关系间的引用。例如:

      • 学生实体、专业实体:

        • 学生(学号,姓名,性别,专业号,年龄)

        • 专业(专业号,专业名)

        • 学生关系引用了专业关系的主码“专业号”。学生关系中的“专业号”值必须是确实存在的专业的专业号,即专业关系中有该专业的记录。

      • 学生、课程、学生与课程之间的多对多联系:

        • 学生(学号,姓名,性别,专业号,年龄)

        • 课程(课程号,课程名,学分)

        • 选修(学号,课程号,成绩)

      • 学生实体及其内部的一对多联系:

        • 学生(学号,姓名,性别,专业号,年龄,班长)

        • “班长”是外码,它引用了本关系的“学号”;“班长”必须是确实存在的学生的学号。

  • 外码(Foreign Key)

    • 定义:设F是基本关系R的一个或一组属性,但不是关系R的码。如果F与基本关系S的主码Ks相对应,则称F是基本关系R的外码。基本关系R称为参照关系(Referencing Relation),基本关系S称为被参照关系(Referenced Relation)或目标关系(Target Relation)。

    • 例如:

      • 学生关系的“专业号”与专业关系的主码“专业号”相对应。“专业号”属性是学生关系的外码;专业关系是被参照关系,学生关系为参照关系。

      • 选修关系的“学号”与学生关系的主码“学号”相对应;选修关系的“课程号”与课程关系的主码“课程号”相对应。“学号”和“课程号”是选修关系的外码;学生关系和课程关系均为被参照关系;选修关系为参照关系。

      • “班长”与本身的主码“学号”相对应。“班长”是外码;学生关系既是参照关系也是被参照关

        系。

    • 说明:

      • 关系R和S不一定是不同的关系。

      • 目标关系S的主码Ks和参照关系的外码F必须定义在同一个(或一组)域上。

      • 外码并不一定要与相应的主码同名,当外码与相应的主码属于不同关系时,往往取相同的名字,以便于识别。

  • 参照完整性规则

    • 参照完整性规则:若属性(或属性组)F是基本关系R的外码,它与基本关系S的主码Ks相对应(基本关系R和S不一定是不同的关系),则对于R中每个元组在F上的值必须为:

      • 或者取空值(F的每个属性值均为空值)。

      • 或者等于S中某个元组的主码值。

    • 例如:

      • 学生关系中每个元组的“专业号”属性只取两类值:

        • 空值,表示尚未给该学生分配专业。

        • 非空值,这时该值必须是专业关系中某个元组的“专业号”值,表示该学生不可能分配一个不存在的专业。

      • 选修(学号,课程号,成绩)。“学号”和“课程号”可能的取值:

        • 选修关系中的主属性,不能取空值。

        • 只能取相应被参照关系中已经存在的主码值。

      • 学生(学号,姓名,性别,专业号,年龄,班长)。“班长”属性值可以取两类值:

        • 空值,表示该学生所在班级尚未选出班长。

        • 非空值,该值必须是本关系中某个元组的学号值。

2.3.3 用户定义的完整性

  • 针对某一具体关系数据库的约束条件,反映某一具体应用所涉及的数据必须满足的语义要求。

  • 关系模型应提供定义和检验这类完整性的机制,以便用统一的系统的方法处理它们,而不要由应用程序承担这一功能。

  • 例如:课程(课程号,课程名,学分)。“课程号”属性必须取唯一值,非主属性“课程名”也不能取空值,“学分”属性只能取值{1,2,3,4}。

2.4 关系代数

  • 关系代数:关系代数是一种抽象的查询语言,是对关系的运算来表达查询。关系代数的运算对象是关系,运算结果也是关系。关系代数按运算符的不同可分为传统的集合运算和专门的关系运算两类。集合运算是从关系的水平方向即行的角度进行。专门的关系运算不仅涉及行而且涉及列。

  • 运算符

    • 集合运算符:∪(并)、-(差)、∩(交)、×(笛卡尔积)。

    • 专门的关系运算符:σ(选择)、π(投影)、(连接)、÷(除)。

2.4.1 传统的集合运算

  • 并(union)

    • 关系R和S具有相同的目n(即两个关系都有n个属性),相应的属性取自同一个域。

    • R与S的并运算表示为R∪S:R∪S={t|t∈R∨t∈S}。

    • 运算结果为:n目关系,由属于R或属于S的元组组成。

  • 差(except)

    • 关系R和S具有相同的目n(即两个关系都有n个属性),相应的属性取自同一个域。

    • R与S的差运算表示为R-S:R-S={t|t∈R∧t∉S}。

    • 运算结果为:n目关系,由属于R而不属于S的所有元组组成。

  • 交(intersection)

    • 关系R和S具有相同的目n(即两个关系都有n个属性),相应的属性取自同一个域。

    • R与S的交运算表示为R∩S:R∩S={t|t∈R∧t∈S},R∩S=R-(R-S)。

    • 运算结果为:n目关系,由既属于R又属于S的元组组成。

  • 笛卡尔积(Cartesian Product)

    • 严格地讲应该是广义的笛卡尔积(Extended Cartesian Product)。

    • R:n目关系,k1个元组,S:m目关系,k2个元组。

    • R与S的笛卡尔积运算表示为R×S:

      • 运算结果为:行:k1×k2个元组,列:(n+m)列元组的集合,其中元组的前n列是关系R的一个元组,后m列是关系S的一个元组。

      • { | } r s r s R S t t t R t S     

2.4.2 专门的关系运算

  • 相关记号说明

    • 关系模式为R(A1,A2,…,An),它的一个关系为R,t∈R表示t是R的一个元组。t[Ai]则表示元组t中相应于属性Ai的一个分量。

    • 若A={Ai1,Ai2,…,Aik},其中Ai1,Ai2,…,Aik是A1,A2,…,An中的一部分,则A称为属性列或属性组。t[A]=(t[Ai1],t[Ai2],…,t[Aik])表示元组t在属性列A上诸分量的集合。A 则表示{A1,A2,…,An}中去掉{Ai1,Ai2,…,Aik}后剩余的属性组。

    • R为n目关系,S为m目关系,tr∈R,ts∈S, 称为元组的连接。 是一个n+m列的元组,前n个分量为R中的一个n元组,后m个分量为S中的一个m元组。

    • 给定一个关系R(X,Z),X和Z为属性组。当t[X]=x时,x在R中的象集(Images Set)Zx为:Zx={t[Z]|t∈R,t[X]=x},它表示R中属性组X上值为x的诸元组在Z上分量的集合。

  • 选择(Selection)

    • 选择又称为限制(Restriction)。在关系R中选择满足给定条件的诸元组,记作:

      • σF(R)={t|t∈R∧F(t)='真'}

    • 其中:F为选择条件,基本形式为:X1θY1。

    • 其中,θ表示比较运算符,它可以是>,≥,<,≤,=或<>。X1,Y1等是属性名,或为常量,或为简单函数;属性名也可以用它的序号来代替。

    • 例如:

      • 查询信息系(IS系)全体学生:σSdept='IS'(Student)或σ5='IS'(Student)。

      • 查询年龄小于20岁的学生:σSage<20(Student)或σ4<20(Student)。

  • 投影(Projection)

    • 从R中选择出若干属性列组成新的关系。

      • πA(R)={t[A]|t∈R}

    • 其中:A:R中的属性列。投影操作主要是从列的角度进行运算,投影之后不仅取消了原关系中的某些列,而且还可能取消某些元组(避免重复行)。

    • 例如:

      • 查询学生的姓名和所在系,即求Student关系上学生姓名和所在系两个属性上的投影:πSname,Sdept(Student)或π2,5(Student)。

      • 查询学生关系Student中都有哪些系:πSdept(Student)。

  • 连接(Join)

    • 又称为θ连接,表示从两个关系的笛卡尔积中选取属性间满足一定条件的元组。

    • A和B:分别为R和S上度数相等且可比的属性组。

    • θ:比较运算符。

    • 运算结果:从R和S的广义笛卡尔积R×S中选取(R关系)在A属性组上的值与(S关系)在B属性组上值满足比较关系θ的元组。

    • 两类常用连接运算:

      • 等值连接(equijoin):θ为“=”的连接运算称为等值连接。等值连接的含义:从关系R与S的广义笛卡尔积中选取A、B属性值相等的那些元组。

      • 自然连接(Natural join):自然连接是一种特殊的等值连接,两个关系中进行比较的分量必须是相同属性组,在结果中把重复的属性列去掉。自然连接的含义:R和S具有相同的属性组B。

    • 注意:自然连接还需要取消重复列,所以是同时从行和列的角度进行运算。

    • 例如:

      • 运算关系R和关系S一般连接:

      • 运算关系R和关系S等值连接:

      • 运算关系R和关系S自然连接:

    • 悬浮元组:两个关系R和S在自然连接时,关系R和S中被舍弃的元组称为悬浮元组。

    • 外连接:如果把悬浮元组舍弃的元组也保存在结果关系中,而在其他属性上填空值(Null),这种连接就叫做外连接(OUTER JOIN)。

      • 左外连接:如果只保留左边关系R中的悬浮元组叫做左外连接(LEFT OUTER JOIN或LEFT JOIN)。

      • 右外连接:如果只保留右边关系S中的悬浮元组叫做右外连接(RIGHT OUTER JOIN或RIGHT JOIN)。

    • 例如:

      • 运算关系R和关系S的外连接:

      • 运算关系R和关系S的左外连接和右外连接:

  • 除(Division)

    • 给定关系R(X,Y)和S(Y,Z),其中X,Y,Z为属性组。R中的Y与S中的Y可以有不同的属性名,但必须出自相同的域集。

    • R与S的除运算得到一个新的关系P(X),P是R中满足下列条件的元组在X属性列上的投影:元组在X上分量值x的象集Yx包含S在Y上投影的集合,记作:R÷S={tr[X]|tr∈R∧πY(S) Yx}。Yx:x在R中的象集,x=tr[X]。

    • 注意:除操作是同时从行和列角度进行运算。

    • 例如:

      • 关系R、S的除运算R÷S:

      • 分析:

        • 在关系R中,A可以取四个值{a1,a2,a3,a4}。

        • a1的象集为{(b1,c2),(b2,c3),(b2,c1)}。

        • a2的象集为{(b3,c7),(b2,c3)}。

        • a3的象集为{(b4,c6)}。

        • a4的象集为{(b6,c6)}。

        • S在(B,C)上的投影为{(b1,c2),(b2,c1),(b2,c3)}。

        • 只有a1的象集包含了S在(B,C)属性组上的投影,所以R÷S={a1}。

    • 以学生-课程数据库为例,给出几个综合应用多种关系代数运算进行查询的例子:

      • 查询至少选修1号课程和3号课程的学生号码:

        • 首先建立一个临时关系K:

        • 然后求:πSno,Cno(SC)÷K,结果为{201215121}。

        • 求解过程:先对SC关系的(Sno,Cno)属性上投影,然后逐一求出每一学生(Sno)的象集,并依此检查这些象集是否包含K。

      • 查询选修了2号课程的学生的学号:

        • πSno(σCno=‘2’(SC))={201215121,201215122}。

      • 查询至少选修了一门其直接先行课为5号课程的课程的学生姓名:

        • πSname(σCpno=‘5’(Course) SC πSno,Sname(Student))。

        • 或:

          • πSname(πSno(σCpno=‘5’(Course) SC) πSno,Sname(Student))。

      • 查询选修了全部课程的学生号码和姓名:

        • πSno,Cno(SC)÷πCno ( Course) πSno,Sname(Student)。

2.5 关系演算

  • 关系演算:关系演算是以数理逻辑中的谓词演算为基础的。按谓词变元的不同,关系演算可分为元组关系演算和域关系演算。

2.5.1 元组关系演算语言ALPHA

  • 元组关系演算:元组关系演算以元组变量作为谓词变元的基本对象。一种典型的元组关系演算语言是ALPHA语言。

  • ALPHA语言:主要有GET,PUT,HOLD,UPDATE,DELETE,DROP 6条语句。

  • 语句的基本格式

    • 操作语句 工作空间名(表达式):操作条件

    • 表达式用于说明要查询的结果,它可以是关系名或(和)属性名。

    • 操作条件是一个逻辑表达式,说明查询结果要满足的条件,用于将操作结果限定在满足条件的元组中,操作条件可以为空。

    • 除此之外,还可以在基本格式的基础上加上排序要求、定额要求等。

  • 检索操作

    • 简单检索(即不带条件的检索):

      • 查询所有被选修的课程号码:Get W(SC.Cno)。

      • 查询所有学生的数据:GET W(Student)。

    • 限定的检索(即带条件的检索):

      • 查询信息系(IS)中年龄小于20岁的学生的学号和年龄:GET W(Student.Sno,Student.Sage):Student.Sdept=‘IS’ ∧Student.Sage<20。

    • 带排序的检索:

      • 查询计算机科学系(CS)学生的学号、年龄,结果按年龄降序排序:GET W(Student.Sno,Student.Sage):Student.Sdept=‘CS’ DOWN Student.Sage。

    • 指定返回元组的个数:

      • 取出一个信息系学生的学号:GET W(1)(Student.Sno):Student.Sdept=‘IS’。

      • 查询信息系年龄最大的三个学生的学号及其年龄,结果按年龄降序排序:GET W(3)(Student.Sno,Student.Sage):Student.Sdept=‘IS’ DOWN Student.Sage。

    • 用元组变量的检索:

      • 元组变量是在某一关系范围内变化(所以也称为范围变量Range Variable),一个关系可以设多个元组变量。元组变量主要有两方面的用途:

        • 简化关系名。如果关系的名字很长,使用起来就会感到不方便,这时可以设一个较短名字的元组变量来代替关系名。

        • 操作条件中使用量词时必须用元组变量。

      • ALPHA语言用RANGE来说明元组变量。

      • 查询信息系学生的名字:

        • RANGE Student X

        • GET W(X.Sname):X.Sdept=‘IS’。

    • 用存在量词(existential quantifier)的检索条件中使用量词时必须用元组变量:

      • 查询选修2号课程的学生名字:

        • RANGE SC X

        • GET W(Student.Sname): X(X.Sno=Student.Sno∧X.Cno=‘2’)。

      • 查询选修了这样课程的学生学号,其直接先行课是6号课程:

        • RANGE Course CX

        • GET W(SC.Sno): CX(CX.Cno=SC.Cno∧CX.Pcno='6')。

      • 查询至少选修一门其先行课为6号课程的学生名字:

        • RANGE Course CX

        • SC SCX

        • GET W(Student.Sname): SCX(SCX.Sno=Student.Sno ∧ CX(CX.Cno=SCX.Cno∧CX.Pcno=‘6’))。

      • 元组关系演算公式可以变换为前束范式(Prenex normal form)的形式:

        • GET W(Student.Sname): SCX CX(SCX.Sno=Student.Sno ∧CX.Cno=SCX.Sno∧CX.Pcno='6')。

    • 带有多个关系的表达式的检索:

      • 查询成绩为90分以上的学生名字与课程名字:

        • RANGE SC SCX

        • GET W(Student.Sname,Course.Cname): SCX(SCX.Grade≥90 ∧SCX.Sno=Student.Sno∧Course.Cno=SCX.Cno)。

    • 用全称量词(generality quantifier)的检索:

      • 查询不选1号课程的学生名字:

        • RANGE SC SCX

        • GET W(Student.Sname): SCX(SCX.Sno≠Student.Sno∨SCX.Cno≠ '1')。

      • 也可以用存在量词来表示:

        • RANGE SC SCX

        • GET W(Student.Sname): ¬ SCX(SCX.Sno=Student.Sno∧SCX.Cno='1')。

    • 用两种量词的检索:

      • 查询选修了全部课程的学生姓名:

        • RANGE Course CX

        • SC SCX

        • GET W(Student.Sname): CX SCX(SCX.Sno = Student.Sno ∧ SCX.Cno = CX.Cno)。

    • 用蕴涵(Implication)的检索:

      • 查询最少选修201215122学生所选课程的学生学号:

        • RANGE Course CX

        • SC SCX(注意:这里SC设了两个元组变量)

        • SC SCY

        • GET W(Student.Sno): CX( SCX(SCX.Sno=‘201215122’∧ SCX.Cno=CX.Cno) SCY(SCY.Sno=Student.Sno∧SCY.Cno = CX.Cno))。

    • 聚集函数:

      • 使用查询语言时,进行简单的计算。关系数据语言中建立了有关这类运算的标准函数库。这类函数通常称为聚集函数或内置函数。常用的聚集函数COUNT,TOTAL,MAX,MIN,AVG等。

      • 查询学生所在系的数目:

        • GET W(COUNT(Student.Sdept))。

      • 查询信息系学生的平均年龄:

        • GET W(AVG(Student.Sage)):Student.Sdept='IS'。

  • 更新操作

    • 修改操作:

      • 修改操作用UPDATE语句实现。其步骤是:

        • 首先用HOLD语句将修改的元组从数据库中读到工作空间中。

        • 然后用宿主语言修改工作空间中元组的属性值。

        • 最后用UPDATE语句将修改后的元组送回数据库中。

      • 注意:

        • 单纯检索数据使用GET语句即可,但为修改数据而读元组时必须使用 HOLD语句,HOLD语句是带上并发控制的GET语句。

        • 如果修改操作涉及到两个关系的话,就要执行两次HOLD MOVE-UPDATE操作序列。

        • 在ALPHA语言中,修改关系主码的操作是不允许的,例如不能用UPDATE语句将学号201215121改为201215122。

        • 如果需要修改主码值,只能先用删除操作删除该元组,然后再把具有新主码值的元组插入到关系中。

      • 把201215127学生从计算机科学系转到信息系:

        • HOLD W(Student.Sno,Student.Sdept):Student.Sno= ‘201215127’。

        • MOVE ‘IS’TO W.Sdept。

        • UPDATE W。

    • 插入操作:

      • 插入操作用PUT语句实现。其步骤是:

        • 首先用宿主语言在工作空间中建立新元组。

        • 然后用PUT语句把该元组存入指定的关系中。

      • PUT语句只对一个关系操作,也就是说表达式必须为单个关系名。

      • 学校新开设了一门2学分的课程“计算机组织与结构”,其课程号为8号,直接先行课为6号课程。插入该课程元组:

        • MOVE ‘8’TO W.Cno。

        • MOVE ‘计算机组织与结构’TO W.Cname。

        • MOVE ‘6’TO W.Cpno。

        • MOVE ‘2’TO W.Ceredit。

        • PUT W(Course)。

    • 删除操作:

      • 删除操作用DELETE语句实现。其步骤为:

        • 用HOLD语句把要删除的元组从数据库中读到工作空间中。

        • 用DELETE语句删除该元组。

      • 201215230学生因故退学,删除该学生元组:

        • HOLD W(Student):Student.Sno=‘201215230’。

        • DELETE W。

      • 将学号201215121改为201215122:

        • HOLD W(Student):Student.Sno=‘201215121’。

        • DELETE W。

        • MOVE ‘201215122’TO W.Sno。

        • MOVE ‘李勇’TO W.Sname。

        • MOVE ‘男’TO W.Ssex。

        • MOVE ‘20’TO W.Sage。

        • MOVE ‘CS’TO W.Sdept。

        • PUT W(Student)。

      • 删除全部学生:

        • HOLD W(Student)。

        • DELETE W。

      • 由于SC关系与Student关系之间的具有参照关系,为保证参照完整性,删除Student中元组时相应地要删除SC中的元组(手工删除或由DBMS自动执行):

        • HOLD W(SC)。

        • DELETE W。

2.5.2 元组关系演算

为了讨论方便,先允许关系(的基数)是无限的。然后再对这种情况下定义的演算作适当的修改,保证关系演算中的每一个公式表示的是有限关系。

在元组关系演算系统中,称 {t|φ(t)} 为元组演算表达式。其中 t 是元组变量,φ(t) 为元组关系演算公式,简称公式。它由原子公式和运算符组成。

原子公式

原子公式有三类:

  1. R(t)

    • R是关系名,t是元组变量。R(t)表示t是R中的元组。于是,关系R可表示为 {t|R(t)}

  2. t[i]θu[j]

    • t和u是元组变量,θ是算术比较运算符。t[i]θu[j] 表示断言“元组t的第i个分量与元组u的第j个分量满足比较关系θ”。

    • 例如:t[2]<u[3],表示元组t的第2个分量小于元组u的第3个分量。

  3. t[i]θc 或 cθt[i]

    • 这里c是常量,该公式表示“t的第i个分量与常量C满足比较关系θ”。

    • 例如:t[4]=3 表示元组t的第4个分量等于3。

在关系演算中定义了“自由元组变量”和“约束元组变量”的概念。这些概念和谓词演算中的概念完全一样。若公式中的一个元组变量前有“全称量词”或“存在量词”,则称该变量为约束元组变量,否则称自由元组变量。

公式递归定义

公式可以递归定义如下:

  1. 每个原子公式是公式。

  2. 如果 φ1φ2 是公式,则 φ1∧φ2φ1∨φ2¬φ1 也是公式。分别表示:

    • 如果 φ1φ2 同时为真,则 φ1∧φ2 才为真,否则为假。

    • 如果 φ1φ2 中一个或同时为真,则 φ1∨φ2 为真,仅当 φ1φ2 同时为假时,φ1∨φ2 才为假。

    • φ1 为真,则 ¬φ1 为假。

  3. φ 是公式,则 ∃t(φ) 也是公式。其中符号 是存在量词符号,∃t(φ) 表示:若有一个t使 φ 为真,则 ∃t(φ) 为真,否则 ∃t(φ) 为假。

  4. φ 是公式,则 ∀t(φ) 也是公式。其中符号 是全称量词符号,∀t(φ) 表示:如果对所有t,都使 φ 为真,则 ∀t(φ) 为真,否则 ∀t(φ) 为假。

  5. 在元组演算公式中,各种运算符的优先次序为:

    • 算术比较运算符最高。

    • 量词次之,且 的优先级高于 的优先级。

    • 逻辑运算符最低,且 的优先级高于 的优先级, 的优先级高于 的优先级。

    • 加括号时,括号中运算符优先,同一括号内的运算符之优先级遵循上述各项。

  6. 有限次地使用上述五条规则得到的公式是元组关系演算公式,其他公式不是元组关系演算公式。

一个元组演算表达式 {t|φ(t)} 表示了使 φ(t) 为真的元组集合。关系代数的运算均可以用关系演算表达式来表示(反之亦然)。

关系代数运算的表达式

下面用关系演算表达式来表示五种基本运算:

    • R∪S={t|R(t)∨S(t)}

    • R-S={t|R(t)∧¬S(t)}

  1. 笛卡尔积

    • R×S={t(n+m)|(∃u(n))(∃v(m))(R(u)∧S(v)∧t[1]=u[1]∧…∧t[n]=u[n]∧t[n+1]=v[1]∧…∧t[n+m]=v[m])}

      • 这里 t(n+m) 表示t的目数是 (n+m)

  2. 投影

    • πA(R)={t(k)|(∃u(n))(R(u)∧t[1]=u[i1]∧…∧t[k]=u[ik])}

      • 其中k是属性组A中属性的个数,i1,i2,…,ik是A中属性在关系R中的位置序号。

  3. 选择

    • σF(R)={t|R(t)∧F′}

      • F′ 是公式F用 t[i] 代替运算对象i得到的等价公式。

学生-课程数据库查询

下面用关系演算来对学生-课程数据库进行查询:

  1. 查询信息系(IS)系全体学生:

    • SIS={t|Student(t)∧t[5]='IS'}

  2. 查询年龄小于20岁的学生:

    • S20={t|Student(t)∧t[4]<20}

  3. 查询学生的姓名和所在系:

    • S1={t(2)|(∃u)(Student(u)∧t[1]=u[2]∧t[2]=u[5])}

安全限制

定义 dom(φ)dom(φ) 是一个有限的符号集,一定包括出现在 φ 以及中间结果和最后结果的关系中的所有符号(实际上各列中值的汇集),dom(φ) 不必是最小集。

当满足下列条件时,元组演算表达式 {t|φ(t)} 是安全的:

  1. 如果t使 φ(t) 为真,则t的每个分量是 dom(φ) 中的元素。

  2. 对于 φ 中每一个形如 (∃u)(W(u)) 的子表达式,若u使 W(u) 为真,则u的每个分量是 dom(φ) 中的元素。

  3. 对于 φ 中每一个形如 (∀u)(W(u)) 的子表达式,若u使 W(u) 为假,则u的每个分量必属于 dom(φ)。换言之,若u某一分量不属于 dom(φ),则 W(u) 为真。

例如:设有关系R如下图,S={t|¬R(t)},若不进行安全限制,则可能是一个无限关系。

定义 dom(φ)=πA(R)∪πB(R)∪πC(R)={{a1,a2},{b1,b2},{c1,c2}}。

则S是 dom(φ) 中各域值中元素的笛卡尔积与R的差集。结果如下图:

ABC
a1b1c1
a2b2c2
ABC
a1b1c2
a1b2c1
a1b2c2
a2b1c1
a2b1c2
a2b2c1

2.5.3 域关系演算语言QBE

关系演算的另一种形式是域关系演算。域关系演算以元组变量的分量即域变量作为谓词变元的基本对象。

1975年由M. M. Zloof提出的QBE就是一个很有特色的域关系演算语言,该语言于1978年在IBM370上得以实现。

QBE是Query By Example(即通过例子进行查询)的简称,它是基于屏幕表格的查询语言,用户通过终端屏幕编辑程序以填写表格的方式构造查询要求,而查询结果也是以表格形式显示。QBE中用示例元素来表示查询结果可能的情况,示例元素实质上就是域变量。

QBE操作框架
  1. 检索操作

    • 简单查询

      • 例如:求信息系全体学生的姓名。操作步骤为:

        1. 用户提出要求。

        2. 屏幕显示空白表格。

        3. 用户在最左边一栏输入关系名Student。

        4. 系统显示该关系的属性名。

        5. 用户在上面构造查询要求。

        6. 屏幕显示查询结果。

      • 例如:查询全体学生的全部数据。

        • 显示全部数据也可以简单地把P.操作符作用在关系名上。

    • 条件查询

      • 例如:求年龄大于19岁的学生的学号。

      • 例如:求计算机科学系年龄大于19岁的学生的学号。

        • 查询条件是Sdept=‘CS’和Sage>19两个条件的“与”。在QBE中,表示两个条件的“与”有两种方法:

          1. 把两个条件写在同一行上。

          2. 把两个条件写在不同行上,用相同的示例元素值。

      • 例如:查询计算机科学系或者年龄大于19岁的学生的学号。

        • 本查询的条件是Sdept='CS'和Sage>19两个条件的“或”。在QBE中把两个条件写在不同行上,并且使用不同的示例元素值,即表示条件的“或”。

      • 例如:查询既选了1号课程又选了2号课程的学生学号。

        • 查询条件是在一个属性中的“与”关系,它只能用“与”条件的第(2)种方法表示,即写两行,示例元素相同。

      • 例如:查询选修1号课程的学生姓名。

        • 本查询涉及两个关系:SC和Student。在QBE中实现这种查询的方法是通过相同的连接属性值把多个关系连接起来。

        • 这里示例元素Sno是连接属性,其值在两个表中要相同。

      • 例如:查询未选修1号课程的学生姓名。

        • 这里的查询条件中用到逻辑非。在QBE中表示逻辑非的方法是将逻辑非写在关系名下面。

        • 这个查询就是显示学号为201215121的学生名字,而该学生选修1号课程的情况为假或者学生(201215121)什么课程都每一选修。

      • 例如:查询有两个人以上选修的课程号。

        • 本查询是在一个表内连接。这个查询就是要显示这样的课程1,它不仅被201215121选修,而且也被另一个学生( 201215121 )选修了。

    • 聚集函数

      • 为了方便用户,QBE提供了一些聚集函数,主要包括CNT,SUM,AVG,MAX,MIN等,其含义如下。

        • 函数名 功能

        • CNT 对元组计数

        • SUM 求总和

        • AVG 求平均值

        • MAX 求最大值

        • MIN 求最小值

      • 例如:查询信息系学生的平均年龄。

    • 对查询结果排序

      • 对查询结果按某个属性值的升序排序,只需在相应列中填入“AO.”,按降序排序则均“DO.”。如果按多列排序,用“AO(i).”或“DO(i).”表示,其中i为排序的优先级,i值越小,优先级越高。

      • 例如:查全体男生的姓名,要求查询结果按所在系升序排序,对相同系的学生按年龄降序排序。

  2. 更新操作

    • 修改操作

      • 修改操作符为“U.”。

      • 在QBE中,关系的主码不允许修改,如果需要修改某个元组的主码,只能先删除该元组,然后再插入新的主码的元组。

      • 例如:把201215121学生的年龄改为18岁。

        • 这是修改操作不包含算术表达式,可以有两种表示方法:

          1. 将操作符“U.”放在值上。

          2. 将操作符“U.”放在关系上。

        • 主码201215121标明要修改的元组,U.标明所在的行是修改后的新值。因主码是不能修改的,即使在第二种写法中,系统也不会混淆要修改的属性。

      • 例如:把201215121学生的年龄增加1岁。

        • 这个修改操作涉及表达式,所以只能将操作符“U.”放在关系上。

      • 例如:将计算机科学系所有学生的年龄都增加1岁。

    • 插入操作

      • 插入操作符为“I.”。新插入的元组必须具有码值,其他属性值可以为空。

      • 例如:把信息系女生201215801,姓名张三,年龄17岁存入数据库中。

    • 删除操作

      • 删除操作符为“D.”。

      • 例如:删除学生201215189。

        • SC关系与Student关系之间具有参照关系,为保证参照完整性,删除201215189学生后,还应删除201215189学生选修的全部课程。

第3章 关系数据库标准语言SQL

3.1 SQL概述

SQL(Structured Query Language):结构化查询语言,是关系数据库的标准语言。SQL是一个通用的、功能极强的关系数据库语言。

3.1.1 SQL的产生与发展

  • SQL标准的进展过程。

3.1.2 SQL的特点

  1. 综合统一

    • 集数据定义语言(DDL),数据操纵语言(DML),数据控制语言(DCL)功能于一体。

    • 可以独立完成数据库生命周期中的全部活动:定义关系模式,插入数据,建立数据库;对数据库中的数据进行查询和更新;数据库重构和维护;数据库安全性、完整性控制等。

    • 用户数据库投入运行后,可根据需要随时逐步修改模式,不影响数据的运行。

    • 数据操作符统一。

  2. 高度非过程化

    • 非关系数据模型的数据操纵语言“面向过程”,必须制定存取路径。

    • SQL只要提出“做什么”,无须了解存取路径。

    • 存取路径的选择以及SQL的操作过程由系统自动完成。

  3. 面向集合的操作方式

    • 非关系数据模型采用面向记录的操作方式,操作对象是一条记录。

    • SQL采用集合操作方式:

      • 操作对象、查找结果可以是元组的集合。

      • 一次插入、删除、更新操作的对象可以是元组的集合。

  4. 以同一种语法结构提供多种使用方式

    • SQL是独立的语言,能够独立地用于联机交互的使用方式。

    • SQL又是嵌入式语言,能够嵌入到高级语言(例如C,C++,Java)程序中,供程序员设计程序时使用。

  5. 语言简洁,易学易用

    • SQL功能极强,完成核心功能只用了9个动词:

      • 数据查询:SELECT

      • 数据定义:CREATE,DROP,ALTER

      • 数据操纵:INSERT,UPDATE,DELETE

      • 数据控制:GRANT,REVOKE

3.1.3 SQL的基本概念

  • SQL支持关系数据库三级模式结构

    • 基本表

      • 本身独立存在的表。

      • SQL中一个关系就对应一个基本表。

      • 一个(或多个)基本表对应一个存储文件。

      • 一个表可以带若干索引。

    • 存储文件

      • 逻辑结构组成了关系数据库的内模式。

      • 物理结构是任意的,对用户透明。

    • 视图

      • 从一个或几个基本表导出的表。

      • 数据库中只存放视图的定义而不存放视图对应的数据。

      • 视图是一个虚表。

      • 用户可以在视图上再定义视图。

3.2 学生-课程数据库

学生-课程模式S-T:

  • 学生表:Student(Sno,Sname,Ssex,Sage,Sdept)

    • 学号 Sno

    • 姓名 Sname

    • 性别 Ssex

    • 年龄 Sage

    • 所在系 Sdept

    • 数据示例:

      • 200215121 李勇 男 20 CS

      • 200215122 刘晨 女 19 CS

      • 200215123 王敏 女 18 MA

      • 200215125 张立 男 19 IS

  • 课程表:Course(Cno,Cname,Cpno,Ccredit)

    • 课程号 Cno

    • 课程名 Cname

    • 先行课 Cpno

    • 学分 Ccredit

    • 数据示例:

      • 1 数据库 5 4

      • 2 数学 2

      • 3 信息系统 1 4

      • 4 操作系统 6 3

      • 5 数据结构 7 4

      • 6 数据处理 2

      • 7 PASCAL 语言 6 4

  • 学生选课表:SC(Sno,Cno,Grade)

    • 学号 Sno

    • 课程号 Cno

    • 成绩 Grade

    • 数据示例:

      • 200215121 1 92

      • 200215121 2 85

      • 200215121 3 88

      • 200215122 2 90

      • 200215122 3 80

3.3 数据定义

SQL的数据定义功能:模式定义、表定义、视图和索引的定义。

3.3.1 模式的定义与删除

  1. 定义模式

    • 语句格式:

      • CREATE SCHEMA <模式名> AUTHORIZATION <用户名>;

    • 示例:

      • 为用户WANG定义一个学生-课程模式S-T:

        • CREATE SCHEMA "S-T" AUTHORIZATION WANG;

    • 说明:

      • 若没有指定模式名,则 <模式名> 隐含为 <用户名>

      • CREATE SCHEMA 中可以接受 CREATE TABLECREATE VIEWGRANT 子句。

      • 执行创建模式语句必须拥有DBA权限,或者DBA授予在 CREATE SCHEMA 的权限。

  2. 删除模式

    • 语句格式:

      • DROP SCHEMA <模式名> <CASCADE|RESTRICT>;

    • 说明:

      • CASCADE和RESTRICT必须二选一。

      • CASCADE(级联):删除模式的同时把该模式中所有的数据库对象全部删除。

      • RESTRICT(限制):如果该模式中定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。当该模式中没有任何下属的对象时才能执行。

    • 示例:

      • 删除模式ZHANG,同时该模式中定义的表TAB1也被删除:

        • DROP SCHEMA ZHANG CASCADE;

3.3.2 基本表的定义、删除与修改

  1. 定义基本表

    • 语句格式:

      • CREATE TABLE <表名> (<列名> <数据类型>[ <列级完整性约束条件>] [,<列名> <数据类型>[ <列级完整性约束条件>]]… [,<表级完整性约束条件> ]);

    • 示例:

      • 建立“学生”表Student,学号是主码,姓名取值唯一:

        • CREATE TABLE Student (
              Sno CHAR(9) PRIMARY KEY,
              Sname CHAR(20) UNIQUE,
              Ssex CHAR(2),
              Sage SMALLINT,
              Sdept CHAR(20)
          );
      • 建立一个“课程”表Course:

        • CREATE TABLE Course (
              Cno CHAR(4) PRIMARY KEY,
              Cname CHAR(40),
              Cpno CHAR(4),
              Ccredit SMALLINT,
              FOREIGN KEY (Cpno) REFERENCES Course(Cno)
          );
      • 建立一个“学生选课”表SC:

        • CREATE TABLE SC (
              Sno CHAR(9),
              Cno CHAR(4),
              Grade SMALLINT,
              PRIMARY KEY (Sno, Cno),
              FOREIGN KEY (Sno) REFERENCES Student(Sno),
              FOREIGN KEY (Cno) REFERENCES Course(Cno)
          );
  2. 数据类型

    • CHAR(n):长度为 n 的定长字符串

    • VARCHAR(n):最大长度为 n 的变长字符串

    • INT:长整数(也可以写作 INTEGER)

    • SMALLINT:短整数

    • NUMERIC(p,d):定点数,由 p 位数字(不包括符号、小数点)组成,小数后面有 d 位数字

    • REAL:取决于机器精度的浮点数

    • Double Precision:取决于机器精度的双精度浮点数

    • FLOAT(n):浮点数,精度至少为 n 位数字

    • DATE:日期,包含年、月、日,格式为 YYYY-MM-DD

    • TIME:时间,包含一日的时、分、秒,格式为 HH:MM:SS

  3. 模式与表

    • 每一个基本表都属于某一个模式,一个模式包含多个基本表。

    • 创建基本表(其他数据库对象也一样)时,若没有指定模式,系统根据搜索路径来确定该对象所属的模式。

      • 显示当前的搜索路径:

        • SHOW search_path;

      • 搜索路径的当前默认值是:

        • $user,PUBLIC

      • DBA用户可以设置搜索路径:

        • SET search_path TO "S-T", PUBLIC;(第一个模式名S-T)

      • 若搜索路径中的模式名都不存在,系统将给出错误。

      • 若搜索路径中存在模式,RDBMS会使用模式列表中第一个存在的模式作为数据库对象的模式名。

    • 创建基本表:

      • 以定义一个学生-课程模式S-T为例:

        • 创建表时给出模式名:

          • CREATE TABLE "S-T".Student(......); /模式名为S-T/

          • CREATE TABLE "S-T".Course(......);

          • CREATE TABLE "S-T".SC(......);

        • 在创建模式语句中同时创建表。

        • 设置所属模式,在创建表名中不必给出模式名。

      • 示例:

        • DBA用户设置搜索路径,然后定义基本表:

          • SET search_path TO "S-T", PUBLIC;

          • CREATE TABLE Student(……);

          • 执行结果:建立了S-T.Student基本表。

  4. 修改基本表

    • 语句格式:

      • ALTER TABLE <表名> [ADD[COLUMN] <新列名> <数据类型> [完整性约束]] [ADD <表级完整性约束>] [DROP [COLUMN ] <列名> [CASCADE|RESTRICT]] [DROP CONSTRAINT<完整性约束名>[RESTRICT|CASCADE ]] [ALTER COLUMN <列名><数据类型>] ;

    • 说明:

      • <表名> 是要修改的基本表。

      • ADD子句用于增加新列、新的列级完整性约束条件和新的表级完整性约束条件。

      • DROP COLUMN子句用于删除表中的列。如果指定了CASCADE短语,则自动删除引用该列的其他对象。如果指定了RESTRICT短语,则如果该列被其他对象引用,关系数据库管理系统将拒绝删除该列。

      • DROP CONSTRAINT子句用于删除指定的完整性约束条件。

      • ALTER COLUMN子句用于修改原有的列定义,包括修改列名和数据类型。

    • 示例:

      • 向Student表增加“入学时间”列,其数据类型为日期型:

        • ALTER TABLE Student ADD S_entrance DATE;

        • 注意:不论基本表中原来是否已有数据,新增加的列一律为空值。

      • 将年龄的数据类型由字符型(假设原来的数据类型是字符型)改为整数:

        • ALTER TABLE Student ALTER COLUMN Sage INT;

      • 增加课程名称必须取惟一值的约束条件:

        • ALTER TABLE Course ADD UNIQUE(Cname);

  5. 删除基本表

    • 语句格式:

      • DROP TABLE <表名>[RESTRICT| CASCADE];

    • 示例:

      • 删除Student表:

        • DROP TABLE Student CASCADE;

    • 说明:

      • RESTRICT:删除表是有限制的。欲删除的基本表不能被其他表的约束所引用。如果存在依赖该表的对象,则此表不能被删除。

      • CASCADE:删除该表没有限制。在删除基本表的同时,相关的依赖对象一起删除。

      • 基本表定义被删除,数据被删除,表上建立的索引、视图、触发器等一般也将被删除。

      • 示例:

        • 删除Student表,若表上建有视图,选择RESTRICT时表不能删除,选择CASCADE时可以删除表,视图也自动被删除:

          • CREATE VIEW IS_Student AS SELECT Sno, Sname, Sage FROM Student WHERE Sdept='IS';

          • DROP TABLE Student RESTRICT; --ERROR: cannot drop table Student because other objects depend on it

          • DROP TABLE Student CASCADE; --可以删除表,视图也自动被删除

    • DROP TABLE 时,SQL2011与3个RDBMS的处理策略比较。

3.3.3 索引的建立与删除

  • 建立索引的目的:加快查询速度。

  • 谁可以建立索引:DBA或表的属主(即建立表的人)。

  • DBMS一般会自动建立以下列上的索引

    • PRIMARY KEY

    • UNIQUE

  • 谁维护索引:DBMS自动完成。

  • 使用索引:DBMS自动选择是否使用索引及使用哪些索引。

  • RDBMS中索引一般采用B+树、HASH索引来实现

    • B+树索引具有动态平衡的优点。

    • HASH索引具有查找速度快的特点。

    • 采用B+树还是HASH索引则由具体的RDBMS来决定。

  • 索引是关系数据库内部实现技术,属于内模式的范畴。

  • CREATE INDEX语句定义索引时,可以定义索引是唯一索引、非唯一索引或聚簇索引。

  1. 建立索引

    • 语句格式:

      • CREATE [UNIQUE] [CLUSTER] INDEX<索引名> ON <表名>(<列名>[<次序>][,<列名>[<次序>]]…);

    • 说明:

      • UNIQUE表明此索引每一个索引值只对应唯一的数据。

    • 示例:

      • 为学生-课程数据库中的Student,Course,SC三个表建立索引:

        • Student表按学号升序建唯一索引:

          • CREATE UNIQUE INDEX Stusno ON Student(Sno);

        • Course表按课程号升序建唯一索引:

          • CREATE UNIQUE INDEX Coucno ON Course(Cno);

        • SC表按学号升序和课程号降序建唯一索引:

          • CREATE UNIQUE INDEX SCno ON SC(Sno ASC,Cno DESC);

      • CLUSTER表示要建立的索引是聚簇索引。聚簇索引是指索引顺序与表中记录的物理顺序一致的索引组织。

      • 示例:

        • 在Student表的Sname列上建立一个聚簇索引:

          • CREATE CLUSTER INDEX Stusname ON Student(Sname);

      • 在最经常查询的列上建立聚簇索引以提高查询效率。

      • 一个基本表上最多只能建立一个聚簇索引。

      • 经常更新的列不宜建立聚簇索引。

  2. 删除索引

    • 语句格式:

      • DROP INDEX <索引名>;

    • 删除索引时,系统会从数据字典中删去有关该索引的描述。

    • 示例:

      • 删除Student表的Stusname索引:

        • DROP INDEX Stusname;

3.3.4 数据字典

  • 数据字典是关系数据库管理系统内部的一组系统表

  • 数据字典记录了数据库中所有的定义信息,包括模式定义、视图定义、索引定义、完整性约束定义、各类用户对数据库的操作权限、统计信息等。

  • RDBMS执行SQL数据定义时,实际就是更新数据字典。

3.4 数据查询

语句格式:

SELECT [ALL|DISTINCT] <目标列表达式>
[, <目标列表达式>]…
FROM<表名或视图名>[, <表名或视图名>]…
[WHERE<条件表达式>] [GROUP BY<列名 1>[HAVING <条件表达式>]] [ORDER BY<列名 2>[ASC|DESC]];
  • 语句中的字母不分大小写。

  • 语句中的, ;等标点符号为英文状态下的半角字符。

  • [ ]中的内容,不是语句必须的内容,只有为了实现某些功能时才添加。

3.4.1 单表查询

功能:对一个表的内容进行查询。

  1. 选择表中的若干列

    • 查询指定列

      • 格式:在SELECT后面指定列名,FROM后面列所在的表名。

      • 示例:

        • 查询全体学生的学号与姓名:

          • SELECT Sno,Sname FROM Student;

        • 查询全体学生的姓名、学号、所在系:

          • SELECT Sname,Sno,Sdept FROM Student;

    • 查询全部列

      • 功能:选出表中所有属性列。

      • 格式:在SELECT关键字后面列出所有列名或将 <目标列表达式> 指定为 *

      • 示例:

        • 查询全体学生的详细记录:

          • SELECT Sno,Sname,Ssex,Sage,Sdept FROM Student;

          • 或:SELECT * FROM Student;

    • 查询经过计算的值

      • 功能:选出表中指定的属性列,并经过计算后输出。

      • 格式:SELECT 子句的 <目标列表达式> 可以为:

        • 算术表达式

        • 字符串常量

        • 函数

        • 列别名

      • 示例:

        • 查询全体学生的姓名及其出生年份:

          • SELECT Sname,2004-Sage FROM Student;

        • 查询全体学生的姓名、出生年份和所有系,要求用小写字母表示所有系名:

          • SELECT Sname,'Year of Birth:',2004-Sage, LOWER(Sdept) FROM Student;

        • 使用列别名改变查询结果的列标题:

          • SELECT Sname NAME,‘Year of Birth:’BIRTH,2004-Sage BIRTHDAY,LOWER(Sdept)DEPARTMENT FROM Student;

  2. 选择表中的若干元组

    • 消除取值重复的行

      • 如果没有指定DISTINCT关键词,则缺省为ALL。

      • 示例:

        • 查询选修了课程的学生学号:

          • SELECT Sno FROM SC;

          • 等价于:SELECT ALL Sno FROM SC;

        • 指定DISTINCT关键词,去掉表中重复的行:

          • SELECT DISTINCT Sno FROM SC;

    • 查询满足条件的元组

      • 查询满足条件的元组可以通过WHERE子句实现,WHERE常用的查询条件如下:

        • 比较:=,>,<,>=,<=,!=,<>,!>,!<NOT + 上述比较运算符

        • 确定范围:BETWEEN ANDNOT BETWEEN AND

        • 确定集合:INNOT IN

        • 字符匹配:LIKENOT LIKE

        • 空值:IS NULLIS NOT NULL

        • 多重条件(逻辑运算):ANDORNOT

      • 示例:

        • 比较大小:

          • 查询计算机科学系全体学生的名字:

            • SELECT Sname FROM Student WHERE Sdept='CS';

          • 查询所有年龄在20岁以下的学生姓名及其年龄:

            • SELECT Sname,Sage FROM Student WHERE Sage<20;

          • 查询考试成绩有不及格的学生的学号:

            • SELECT DISTINCT Sno FROM SC WHERE Grade<60;

        • 确定范围:

          • 谓词:BETWEEN…AND…NOT BETWEEN…AND…

          • 查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄:

            • SELECT Sname,Sdept,Sage FROM Student WHERE Sage BETWEEN 20 AND 23;

          • 查询年龄不在20~23岁之间的学生姓名、系别和年龄:

            • SELECT Sname,Sdept,Sage FROM Student WHERE Sage NOT BETWEEN 20 AND 23;

        • 确定集合:

          • 谓词:IN<值表>NOT IN<值表>

          • 查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别:

            • SELECT Sname,Ssex FROM Student WHERE Sdept IN('IS','MA','CS');

          • 查询既不是信息系、数学系,也不是计算机科学系的学生的姓名和性别:

            • SELECT Sname,Ssex FROM Student WHERE Sdept NOT IN('IS','MA','CS');

        • 字符匹配:

          • 谓词:[NOT] LIKE‘<匹配串>’ [ESCAPE‘<换码字符>’]

          • 说明:

            • 匹配串为固定字符串。

            • 示例:

              • 查询学号为200215121的学生的详细情况:

                • SELECT * FROM Student WHERE Sno LIKE '200215121';

                • 等价于:

                  • SELECT * FROM Student WHERE Sno='200215121';

            • 匹配串为含通配符的字符串。

            • 示例:

              • 查询所有姓刘学生的姓名、学号和性别:

                • SELECT Sname,Sno,Ssex FROM Student WHERE Sname LIKE ‘刘%’;

              • 查询姓“欧阳”且全名为三个汉字的学生的姓名:

                • SELECT Sname FROM Student WHERE Sname LIKE ‘欧阳_’;

              • 查询名字中第二个字为“阳”字的学生的姓名和学号:

                • SELECT Sname,Sno FROM Student WHERE Sname LIKE ‘_阳%’;

              • 查询所有不姓刘的学生姓名、学号和性别:

                • SELECT Sname,Sno,Ssex FROM Student WHERE Sname NOT LIKE ‘刘%’;

            • 使用换码字符将通配符转义为普通字符。

            • 示例:

              • 查询DB_Design课程的课程号和学分:

                • SELECT Cno,Ccredit FROM Course WHERE Cname LIKE ‘DB\_Design’ ESCAPE ‘\\u2019;

              • 查询以“DB_”开头,且倒数第三个字符为i的课程的详细情况:

                • SELECT * FROM Course WHERE Cname LIKE ‘DB\_%i_ _’ ESCAPE ‘\\u2019;

              • 说明:ESCAPE‘\\u2019表示“\u201d为换码字符。

        • 涉及空值的查询:

          • 谓词:IS NULLIS NOT NULL

          • “IS”不能用“=”代替

          • 示例:

            • 某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩学生的学号和相应的课程号:

              • SELECT Sno,Cno FROM SC WHERE Grade IS NULL;

            • 查询所有有成绩的学生学号和课程号:

              • SELECT Sno,Cno FROM SC WHERE Grade IS NOT NULL;

        • 多重条件查询:

          • 用逻辑运算符ANDOR来联结多个查询条件,AND的优先级高于OR,可以用括号改变优先级。

          • 可用来实现多种其他谓词:

            • [NOT] IN

            • [NOT] BETWEEN … AND …

          • 示例:

            • 查询计算机系年龄在20岁以下的学生姓名:

              • SELECT Sname FROM Student WHERE Sdept='CS' AND Sage<20;

            • 查询信息系(IS)、数学系(MA)和计算机科学系(CS)学生的姓名和性别:

              • SELECT Sname, Ssex FROM Student WHERE Sdept IN('IS','MA','CS');

              • 可改写为:

                • SELECT Sname,Ssex FROM Student WHERE Sdept='IS' OR Sdept='MA' OR Sdept='CS';

  3. ORDER BY子句

    • ORDER BY子句可以按一个或多个属性列排序:

      • 升序:ASC

      • 降序:DESC

      • 缺省值为升序。

      • 当排序列含空值时:(空值默认为最大值)

        • ASC:排序列为空值的元组最后显示。

        • DESC:排序列为空值的元组最先显示。

    • 示例:

      • 查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列:

        • SELECT Sno,Grade FROM SC WHERE Cno='3' ORDER BY Grade DESC;

      • 查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列:

        • SELECT * FROM Student ORDER BY Sdept,Sage DESC;

  4. 聚集函数

    • COUNT([DISTINCT|ALL] *):统计元组个数

    • COUNT([DISTINCT|ALL] <列名>):统计一列中值的个数

    • SUM([DISTINCT|ALL] <列名>):计算一列值的总和(此列必须是数值型)

    • AVG([DISTINCT|ALL] <列名>):计算一列值的平均值(此列必须是数值型)

    • MAX([DISTINCT|ALL] <列名>):求一列值的最大值

    • MIN([DISTINCT|ALL] <列名>):求一列值的最大值

    • 示例:

      • 查询学生总人数:

        • SELECT COUNT(*) FROM Student;

      • 查询选修了课程的学生人数:

        • SELECT COUNT(DISTINCT Sno) FROM SC;

      • 查询学生200215012选修课程的总学分数:

        • SELECT SUM(Ccredit) FROM SC,Course WHERE Sno=‘200215012’ AND SC.Cno=Course.Cno;

      • 计算1号课程的学生平均成绩:

        • SELECT AVG(Grade) FROM SC WHERE Cno=‘1’;

      • 查询选修1号课程的学生最高分数:

        • SELECT MAX(Grade) FROM SC WHERE Cno='1';

    • 注意:WHERE子句中是不能用聚集函数作为条件表达式的。聚集函数只能用于SELECT子句和GROUP BY中的HAVING子句。

  5. GROUP BY子句

    • GROUP BY子句作用是:按指定的一列或多列值分组,值相等的为一组,来细化聚集函数的作用对象。

    • 说明:

      • 未对查询结果分组,聚集函数将作用于整个查询结果。

      • 对查询结果分组后,聚集函数将分别作用于每个组。

    • 示例:

      • 求各个课程号及相应的选课人数:

        • SELECT Cno,COUNT(Sno) FROM SC GROUP BY Cno;

      • 查询选修了3门以上课程的学生学号:

        • SELECT Sno FROM SC GROUP BY Sno HAVING COUNT(*)>3;

      • HAVING短语与WHERE子句的区别:

        • 作用对象不同:WHERE子句作用于基表或视图,从中选择满足条件的元组。HAVING短语作用于组,从中选择满足条件的组。

        • WHERE子句中是不能用聚集函数作为条件表达式的。

      • 示例:

        • 查询平均成绩大于等于90分的学生学号和平均成绩。

          • 下面的语句是不对的:

            • SELECT Sno,AVG(Grade) FROM SC WHERE AVG(Grade)>=90 GROUP BY Sno;

          • 正确的查询语句应该是:

            • SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno HAVING AVG(Grade)>=90;

3.4.2 连接查询

  1. 等值与非等值连接查询

    • 连接查询的WHERE子句中用来连接两个表的条件称为连接条件或连接谓词,其一般格式:

      • 格式一:

        • [<表名1>.]<列名1> <比较运算符> [<表名2>.]<列名2>;

        • 其中,比较运算符有:=、>、<、>=、<=、!=

      • 格式二:

        • [<表名1>.]<列名1> BETWEEN [<表名2>.]<列名2> AND [<表名2>.]<列名3>;

    • 注意:

      • 当连接运算符为“=”称为等值连接,其他运算符称为非等值连接。

      • 连接谓词中的列名称为连接字段,并且各连接字段类型必须是可比的,但名字不必是相同的。

    • 示例:

      • 查询每个学生及其选修课程的情况:

        • SELECT Student.*,SC.* FROM Student,SC WHERE Student.Sno=SC.Sno;

        • 查询结果:

          • Student.Sno Sname Ssex Sage Sdept SC.Sno Cno Grade

          • 200215121 李勇 男 20 CS 200215121 1 92

          • 200215121 李勇 男 20 CS 200215121 2 85

          • 200215121 李勇 男 20 CS 200215121 3 88

          • 200215122 刘晨 女 19 CS 200215122 2 90

          • 200215122 刘晨 女 19 CS 200215122 3 80

      • 连接操作的一种执行方法:嵌套循环法(NESTED-LOOP)

        • 首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接件的元组,找到后就将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组。

        • 表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一查找满足连接条件的元组,找到后就将表1中的第二个元组与该元组拼接起来,形成结果表中一个元组。

        • 重复上述操作,直到表1中的全部元组都处理完毕。

      • 自然连接:若在等值连接中把目标列中重复的属性列去掉则为自然连接。

      • 示例:

        • 对上例用自然连接完成:

          • SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student, SC WHERE Student.Sno = SC.Sno;

  2. 自身连接

    • 定义:一个表与其自己进行连接。

    • 说明:

      • 需要给表起别名以示区别。

      • 由于所有属性名都是同名属性,因此必须使用别名前缀。

    • 示例:

      • 查询每一门课的间接先修课(即先修课的先修课)。

        • 为Course表取两个别名,一个是FIRST,另一个是SECOND。

        • FIRST 表(Course 表):

          • Cno Cname Cpno Ccredit

          • 1 数据库 5 4

          • 2 数学 2

          • 3 信息系统 1 4

          • 4 操作系统 6 3

          • 5 数据结构 7 4

          • 6 数据处理 2

          • 7 PASCAL 语言 6 4

        • SECOND 表(Course 表):

          • Cno Cname Cpno Ccredit

          • 1 数据库 5 4

          • 2 数学 2

          • 3 信息系统 1 4

          • 4 操作系统 6 3

          • 5 数据结构 7 4

          • 6 数据处理 2

          • 7 PASCAL 语言 6 4

        • 查询语句:

          • SELECT FIRST.Cno,SECOND.Cpno FROM Course FIRST,Course SECOND WHERE FIRST.Cpno=SECOND.Cno;

        • 查询结果:

          • Cno Pcno

          • 1 7

          • 3 5

          • 5 6

  3. 外连接

    • 普通连接与外连接的区别:

      • 普通连接操作只输出满足连接条件的元组。

      • 外连接操作以指定表为连接主体,将主体表中不满足连接条件的元组一并输出。

    • 外连接分为:

      • 左外连接:列出左边关系中所有的元组。

        • LEFT OUT JOIN SC ON

      • 右外连接:列出右边关系中所有的元组。

        • RIGHT OUT JOIN SC ON

    • 示例:

      • 查询每个学生及其选修课程的情况:

        • SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student,SC WHERE Student.Sno = SC.Sno;

        • 用外连接查询可改为:

          • SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade FROM Student LEFT OUT JOIN SC ON(Student.Sno=SC.Sno);

        • 查询结果:

          • Student.Sno Sname Ssex Sage Sdept Cno Grade

          • 200215121 李勇 男 20 CS 1 92

          • 200213121 李勇 男 20 CS 2 85

          • 200215121 李勇 男 20 CS 3 88

          • 200215122 刘晨 女 19 CS 2 90

          • 200215122 刘晨 女 19 CS 3 80

          • 200215123 王敏 女 18 MA NULL NULL

          • 200215125 张立 男 19 IS NULL NULL

  4. 多表连接

    • 定义:连接操作是两个以上的表进行连接。

    • 示例:

      • 查询每个学生的学号、姓名、选修的课程名及成绩:

        • SELECT Student.Sno,Sname,Cname,Grade FROM Student,SC,Course WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno;

3.4.3 嵌套查询

  • 一个SELECT-FROM-WHERE语句称为一个查询块。

  • 嵌套查询定义:是指将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询。

  • 说明:

    • 子查询中不能使用ORDER BY子句。

    • 层层嵌套方式反映了SQL语言的结构化。

    • 有些嵌套查询可以用连接运算替代。

    • 外层查询(父查询)、内层查询(子查询)。

  • 示例:

    • 查询与“刘晨”在同一个系学习的学生。

      • 外层查询/父查询:

        • SELECT Sname FROM Student

      • 内层查询/子查询:

        • WHERE Sno IN (SELECT Sno FROM SC WHERE Cno= '2' )

      • 完整查询:

        • `SELECT Sname 
          FROM Student 
          WHERE Sno IN (
              SELECT Sno 
              FROM SC 
              WHERE Cno= '2' );

          `

  1. 带有IN谓词的子查询

    • 在嵌套查询中,子查询的结果往往是个集合,用IN谓词表示父查询的条件在子查询结果的集合中。

    • 示例:

      • 查询与“刘晨”在同一个系学习的学生。

        • 方法一:此查询可以分步来完成。

          • 确定“刘晨”所在系名:

            • SELECT Sdept FROM Student WHERE Sname='刘晨';

            • 结果为:CS

          • 查找所有在CS系学习的学生:

            • SELECT Sno,Sname,Sdept FROM Student WHERE Sdept='CS';

          • 将第一步查询嵌入到第二步查询的条件中:

            • SELECT Sno,Sname,Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname='刘晨');

          • 查询结果:

            • Sno Sname Sdept

            • 200215121 李勇 CS

            • 200215122 刘晨 CS

        • 方法二:用自身连接实现

          • SELECT S1.Sno,S1.Sname,S1.Sdept FROM Student S1,Student S2 WHERE S1.Sdept = S2.Sdept AND S2.Sname = '刘晨';

      • 查询选修了课程名为“信息系统”的学生学号和姓名。

        • 方法一:嵌套查询

          • SELECT Sno, Sname FROM Student WHERE Sno IN (SELECT Sno FROM SC WHERE Cno IN (SELECT Cno FROM Course WHERE Cname= ‘信息系统’ ));

        • 方法二:用连接查询

          • SELECT Sno,Sname FROM Student,SC,Course WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno AND Course.Cname=‘信息系统’;

      • 说明:

        • 不相关子查询:子查询的查询条件不依赖于父查询。

        • 相关子查询:子查询的查询条件依赖于父查询,整个查询语句称为嵌套查询。

  2. 带有比较运算符的子查询

    • 当能确切知道内层查询返回单值时,可用比较运算符(><=>=<=!=<>)。

    • 示例:

      • 查询与“刘晨”在同一个系学习的学生。

        • SELECT Sno, Sname, Sdept FROM Student WHERE Sdept IN (SELECT Sdept FROM Student WHERE Sname= ‘刘晨’);

        • SELECT Sno, Sname, Sdept FROM Student WHERE Sdept = (SELECT Sdept FROM Student WHERE Sname= ‘刘晨’);

      • 找出每个学生超过他选修课程平均成绩的课程号。

        • SELECT Sno,Cno FROM SC x WHERE Grade >= (SELECT AVG(Grade) FROM SC y WHERE x.Sno=y.Sno);

        • 可能的执行过程:

          • 从外层查询中取出SC的一个元组x,将元组xSno值(200215121)传送给内层查询。

            • SELECT AVG(Grade) FROM SC y WHERE y.Sno='200215121';

          • 执行内层查询,得到值88(近似值),代替内层查询,得到外层查询:

            • SELECT Sno,Cno FROM SC x WHERE Grade>=88;

          • 执行这个查询得到:(200215121,1)(200215121,3)

          • 外层查询取出下一个元组重复做上述1至3步骤,直到外层的SC元组全部处理完毕。结果为:

            • (200215121,1)(200215121,3)(200215122,2)

  3. 带有ANY(SOME)或ALL谓词的子查询

    • 谓词语义:

      • ANY——任意一个值

      • ALL——所有值

    • 需要配合使用比较运算符:

      • >ANY 大于子查询结果中的某个值;

      • >ALL 大于子查询结果中的所有值;

      • <ANY 小于子查询结果中的某个值;

      • <ALL 小于子查询结果中的所有值;

      • >=ANY 大于等于子查询结果中的某个值;

      • >=ALL 大于等于子查询结果中的所有值;

      • <=ANY 小于等于子查询结果中的某个值;

      • <=ALL 小于等于子查询结果中的所有值;

      • =ANY 等于子查询结果中的某个值;

      • =ALL 等于子查询结果中的所有值(通常没有实际意义);

      • !=(或<>)ANY 不等于子查询结果中的某个值;

      • !=(或<>)ALL 不等于子查询结果中的任何一个值。

    • 示例:

      • 查询非计算机科学系中比计算机科学任意一个学生年龄小的学生姓名和年龄。

        • SELECT Sname,Sage FROM Student WHERE Sage < ANY (SELECT Sage FROM Student WHERE Sdept= 'CS ') AND Sdept <> 'CS' ;

        • 执行过程:

          • RDBMS执行此查询时,首先处理子查询,找出CS系中所有学生的年龄,构成一个集合(2019);

          • 处理父查询,找不是CS系且年龄小于2019的学生。

        • 执行结果:

          • Sname Sage

          • 王敏 18

          • 张立 19

      • 用聚集函数实现上例。

        • SELECT Sname, Sage FROM Student WHERE Sage < (SELECT MAX (Sage) FROM Student WHERE Sdept=‘CS’) AND Sdept < > ‘CS’;

      • 查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄。

        • 方法一:用ALL谓词

          • SELECT Sname, Sage FROM Student WHERE Sage < ALL (SELECT Sage FROM Student WHERE Sdept= ‘CS’) AND Sdept < > ‘CS’;

        • 方法二:用聚集函数

          • SELECT Sname, Sage FROM Student WHERE Sage < (SELECT MIN (Sage) FROM Student WHERE Sdept=‘CS’) AND Sdept < >‘CS’;

      • 说明:

        • 用聚集函数实现子查询要比直接用ANYALL效率更高。ANYALL谓词与聚集函数、IN谓词的等价转换关系如下表。

          • =<>或!=<<=>>=
            ANYIN--<MAX<=MAX>MIN
            ALL--NOT IN<MIN<=MIN>MAX
  4. 带有EXISTS谓词的子查询

    • (1)EXISTS谓词

      • EXISTS谓词代表存在量词,带有EXISTS谓词的子查询只返回逻辑真值“true”或逻辑假值“false”。

      • 示例:

        • 查询所有选修了1号课程的学生姓名。

          • 思路分析:

            • 本查询涉及StudentSC关系;

            • Student中依次取每个Sno值,用此值去检查SC关系;

            • SC中存在这样的元组,其Sno值等于此Student.Sno值且Cno=‘1’,则取此Student.Sname送入结果关系。

          • 用连接运算:

            • SELECT Sname FROM Student, SC WHERE Student.Sno = SC.Sno AND SC.Cno = ‘1’;

          • 用嵌套查询:

            • SELECT Sname FROM Student WHERE EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno = ‘1’);

      • 说明:

        • 使用存在量词EXISTS后,若内层查询结果非空,则外层的WHERE子句返回真值;否则返回假值。

        • EXISTS引出的子查询目标列表都用*,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

    • (2)NOT EXISTS谓词

      • 说明:

        • 若内层查询结果非空,则外层的WHERE子句返回假值;

        • 若内层查询结果为空,则外层的WHERE子句返回真值。

      • 示例:

        • 查询没有选修1号课程的学生姓名。

          • SELECT Sname FROM Student WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno = Student.Sno AND Cno = ‘1’);

    • (3)不同形式的查询间的替换

      • ①一些带EXISTSNOT EXISTS谓词的子查询不能被其他形式的子查询等价替换。

      • ②所有带IN谓词、比较运算符、ANYALL谓词的子查询都能用带EXISTS谓词的子查询等价替换。

      • 示例:

        • 查询与“刘晨”在同一个系学习的学生。用带EXISTS谓词的子查询替换。

          • SELECT Sno,Sname,Sdept FROM Student S1 WHERE EXISTS (SELECT * FROM Student S2 WHERE S2.Sdept=S1.Sdept AND S2.Sname='刘晨');

    • (4)用EXISTS/NOT EXISTS实现全称量词

      • SQL语言中没有全称量词(For all)。可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:

        • (∀x)P≡¬(∃x(¬P))

      • 示例:

        • 查询选修了全部课程的学生姓名。

          • 等价于:没有一门课是他不选修的。

          • SELECT Sname FROM Student WHERE NOT EXISTS (SELECT * FROM Course WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno));

    • (5)用EXISTS/NOT EXISTS实现逻辑蕴涵

      • SQL语言中没有蕴涵(Implication)逻辑运算,可以利用谓词演算将逻辑蕴涵谓词等价转换为:

        • p→q≡¬p∨q

      • 示例:

        • 查询至少选修了学生201215122选修的全部课程的学生学号

          • 等价于:不存在这样的课程y,学生201215122选修了y,而学生x没有选。

          • SELECT Sno FROM SC WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno='201215122' AND Cno NOT IN (SELECT Cno FROM SC WHERE Sno=SC.Sno));

3.4.4 集合查询

  • 集合操作的种类:并操作、交操作、差操作

  1. 并操作UNION

    • 示例:

      • 查询计算机科学系的学生及年龄不大于19岁的学生。

        • 方法一:

          • SELECT * FROM Student WHERE Sdept='CS';

          • UNION

          • SELECT * FROM Student WHERE Sage<=19;

        • 方法二:

          • SELECT DISTINCT * FROM Student WHERE Sdept='CS' OR Sage<=19;

      • 查询选修了课程1或者选修了课程2的学生。

        • SELECT Sno FROM SC WHERE Cno='1';

        • UNION

        • SELECT Sno FROM SC WHERE Cno='2';

  2. 交操作INTERSECT

    • 示例:

      • 查询计算机科学系的学生与年龄不大于19岁的学生的交集。

        • SELECT * FROM Student WHERE Sdept='CS';

        • INTERSECT

        • SELECT * FROM Student WHERE Sage<=19;

        • 上述例子实际上就是查询计算机科学系中年龄不大于19岁的学生。

        • SELECT * FROM Student WHERE Sdept='CS' AND Sage<=19;

      • 查询选修课程1的学生集合与选修课程2的学生集合的交集。

        • SELECT Sno FROM SC WHERE Cno='1';

        • INTERSECT

        • SELECT Sno FROM SC WHERE Cno='2';

        • 上述例子实际上是查询既选修了课程1又选修了课程2的学生。

        • SELECT Sno FROM SC WHERE Cno='1' AND Sno IN(SELECT Sno FROM SC WHERE Cno='2');

  3. 差操作EXCEPT

    • 示例:

      • 查询计算机科学系的学生与年龄不大于19岁的学生的差集。

        • SELECT * FROM Student WHERE Sdept='CS';

        • EXCEPT

        • SELECT * FROM Student WHERE Sage<=19;

        • 上述例子实际上就是查询计算机科学系中年龄大于19岁的学生。

        • SELECT * FROM Student WHERE Sdept='CS' AND Sage>19;

      • 说明:参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同。

3.4.5 基于派生表的查询

  • 子查询不仅可以出现在WHERE子句中,还可以出现在FROM子句中,这时子查询生成的临时派生表(derived table)成为主查询的查询对象。

  • 示例:

    • 找出每个学生超过他自己选修课程平均成绩的课程号。

      • SELECT Sno,Cno FROM SC,(SELECT Sno,Avg(Grade) FROM SC GROUP BY Sno) AS Avg_sc(avg_sno,avg_grade) WHERE SC.Sno=Avg_sc.avg_sno and SC.Grade >= Avg_sc.avg_grade;

    • 如果子查询中没有聚集函数,派生表可以不指定属性列,子查询SELECT子句后面的列名为其默认属性。

    • 查询所有选修了1号课程的学生姓名。

      • SELECT Sname FROM Student,(SELECT Sno FROM SC WHERE Cno ='1') AS SC1 WHERE Student.Sno= SC1.Sno;

    • 注意:通过FROM子句生成派生表时,AS关键字可以省略,但必须为派生关系指定一个别名。而对于基本表,别名是可选择项。

3.4.6 SELECT语句的一般格式

SELECT [ALL|DISTINCT] <目标列表达式> [别名] [,<目标列表达式> [别名]] …
FROM <表名或视图名> [别名] [,<表名或视图名> [别名]] …
[WHERE <条件表达式>]
[GROUP BY <列名 1> [HAVING <条件表达式>]]
[ORDER BY <列名 2> [ASC|DESC]]

3.5 数据更新

3.5.1 插入数据
  1. 插入元组

    • 语句格式

      INSERT INTO <表名> [(<属性列1>[,<属性列2 >]…)] VALUES(<常量1> [,<常量2>] …);
    • 功能:将新元组插入指定表中。

    • 说明

      • INTO子句:属性列的顺序可与表中的顺序不一致,没有指定属性列的默认插入全部。

      • VALUES子句:提供的值必须与INTO子句匹配,值与属性列的个数和值的类型要一致。

    • 示例

      • 将一个新学生元组(学号:200215128;姓名:陈冬;性别:;所在系:IS;年龄:18岁)插入到Student表中。

        INSERT INTO Student(Sno,Sname,Ssex,Sdept,Sage) VALUES('200215128','陈冬','男','IS',18);
      • 将学生张成民的信息插入到Student表中。

        INSERT INTO Student VALUES('200215126','张成民','男',18,'CS');
      • 插入一条选课记录('200215128', '1')。

        INSERT INTO SC(Sno,Cno) VALUES('200215128', '1');

        RDBMS将在新插入记录的Grade列上自动地赋空值。

        INSERT INTO SC VALUES('200215128','1',NULL);
  2. 插入子查询结果

    • 语句格式

      INSERT INTO <表名> [(<属性列1> [,<属性列2>]…)];
      子查询;
    • 功能:将子查询结果插入指定表中。

    • 说明

      • SELECT子句目标列必须与INTO子句匹配,值的个数、类型都要一致。

    • 示例

      • 对每一个系,求学生的平均年龄,并把结果存入数据库。

        • 第一步:建表

          CREATE TABLE Dept_age (Sdept CHAR(15) /* 系名*/ Avg_age SMALLINT); /*学生平均年龄*/
        • 第二步:插入数据

          INSERT INTO Dept_age(Sdept,Avg_age) SELECT Sdept,AVG(Sage)FROM Student GROUP BY Sdept;
3.5.2 修改数据
  • 语句格式

    UPDATE <表名> SET <列名>=<表达式>[,<列名>=<表达式>]…[WHERE <条件>];
  • 功能:修改指定表中满足WHERE子句条件的元组。

  • 说明

    • SET子句:指定修改方式,修改的列,修改后取值。

    • WHERE子句:指定要修改的元组,缺省表示修改所有元组。

    • 在执行修改语句时会检查修改操作是否破坏表上已定义的完整性规则。

  1. 修改某一个元组的值

    • 示例:将学生200215121的年龄改为22岁。

      UPDATE Student SET Sage=22 WHERE Sno='200215121';
  2. 修改多个元组的值

    • 示例:将所有学生的年龄增加1岁。

      UPDATE Student SET Sage=Sage+1;
  3. 带子查询的修改语句

    • 示例:将计算机科学系全体学生的成绩置零。

      UPDATE SC SET Grade=0 WHERE Sno IN (SELECT Sno FROM Student WHERE Sdept='CS');
3.5.3 删除数据
  • 语句格式

    DELETE FROM <表名> [WHERE <条件>];
  • 功能:删除指定表中满足WHERE子句条件的元组。

  • 说明

    • WHERE子句:指定要删除的元组,缺省表示要删除表中的全部元组,表的定义仍在。

  1. 删除某一个元组的值

    • 示例:删除学号为200215128的学生记录。

      DELETE FROM Student WHERE Sno='200215128';
  2. 删除多个元组的值

    • 示例:删除所有的学生选课记录。

      DELETE FROM SC;
  3. 带子查询的删除语句

    • 示例:删除计算机科学系所有学生的选课记录。

      DELETE FROM SC WHERE Sno IN (SELECT Sno FROM Student WHERE Sdept='CS');

3.6 空值的处理

  • 空值的存在是因为取值有不确定性,对关系运算带来特殊的问题,所以需要做特殊的处理。

  • SQL语言中允许某些元组的某些属性取空值,一般有以下几种情况:

    1. 该属性有值,但当前不知道它的具体值。

    2. 该属性不应该有值。

    3. 由于某种原因不便于填写。

  1. 空值的产生

    • 示例:向SC表中插入一个元组,学生号是“201215126”,课程号是“1”,成绩为空。

      INSERT INTO SC(Sno,Cno,Grade) VALUES('200215128','1',NULL);

      INSERT INTO SC(Sno,Cno) VALUES('200215128','1');
  2. 空值的判断

    • 判断一个属性的值是否为空值,用IS NULLIS NOT NULL来表示。

    • 示例:从Student表中找出漏填了数据的学生信息。

      SELECT * FROM Student WHERE Sname IS NULL OR Ssex IS NULL OR Sage IS NULL OR Sdept IS NULL;
  3. 空值的约束条件

    • 属性定义(或者域定义)中有NOT NULL约束条件的不能取空值。

    • 加了UNIQUE限制的属性不能取空值。

    • 码属性不能取空值。

  4. 空值的算术运算、比较运算和逻辑运算

    • 算术运算:空值与另一个值(包括另一个空值)的算术运算的结果为空值。

    • 比较运算:空值与另一个值(包括另一个空值)的比较运算的结果为UNKNOWN

    • 逻辑运算:

      • 其中,T表示TRUEF表示FALSEU表示UNKNOWN

      • 逻辑运算表:

        XYX AND YX OR YNOT X
        TTTTF
        TUUTF
        TFFTF
        UTUTU
        UUUUU
        UFFUU
        FTFTT
        FUFUT
        FFFFT
    • 示例:

      • 找出选修1号课程的不及格的学生。

        SELECT Sno FROM SC WHERE Grade<60 AND Cno='1';

        以上查询不及格的学生不包括缺考学生,因此前者使条件Grade<60TRUE,后者使条件值为UNKNOWN

      • 找出选修1号课程的不及格的学生以及缺考的学生。

        SELECT Sno FROM SC WHERE Grade<60 AND Cno='1' UNION SELECT Sno FROM SC WHERE Grade IS NULL AND Cno='1';

        SELECT Sno FROM SC WHERE Cno='1' AND (Grade<60 OR Grade IS NULL);

3.7 视图

  1. 视图的特点

    • 视图是虚表,是从一个或几个基本表(或视图)导出的。

    • 只存放视图的定义,不存放视图对应的数据。

    • 表中的数据发生变化,视图中查询出的数据也随之改变。

  2. 基于视图的操作:查询、删除、受限更新、定义基于该视图的新视图。

3.7.1 定义视图
  1. 建立视图

    • 语句格式

      CREATE VIEW<视图名> [(<列名> [,<列名>]…)] AS <子查询> [WITH CHECK OPTION];
    • 说明

      • 组成视图的属性列名:全部省略或全部指定。

      • 子查询不允许含有ORDER BY子句和DISTINCT短语。

      • RDBMS执行CREATE VIEW语句时只是把视图定义存入数据字典,并不执行其中的SELECT语句。

      • 在对视图查询时,按视图的定义从基本表中将数据查出。

    • 示例

      • 建立信息系学生的视图。

        CREATE VIEW IS_Student AS SELECT Sno,Sname,Sage FROM Student WHERE Sdept='IS';
      • 建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生。

        CREATE VIEW IS_Student AS SELECT Sno,Sname,Sage FROM Student WHERE Sdept='IS' WITH CHECK OPTION;

        上例中因为加入了“WITH CHECK OPTION”,所有DBMS对IS_Student视图的更新操作:

        • 修改操作:自动加上Sdept='IS'的条件。

        • 删除操作:自动加上Sdept='IS'的条件。

        • 插入操作:自动检查Sdept属性值是否为'IS',如果不是,则拒绝该插入操作,如果没有提供Sdept属性值,则自动定义Sdept'IS'

      • 基于多个基表的视图。

        CREATE VIEW IS_S1 (Sno, Sname, Grade) AS SELECT Student.Sno, Sname, Grade FROM Student, SC WHERE Sdept = ‘IS’ AND Student.Sno = SC.Sno AND SC.Cno = ‘1’;
      • 基于视图的视图。

        CREATE VIEW IS_S2 AS SELECT Sno,Sname,Grade FROM IS_S1 WHERE Grade>=90;
      • 带表达式的视图。

        CREATE VIEW BT_S(Sno,Sname,Sbirth) AS SELECT Sno,Sname,2000-Sage FROM Student;
      • 分组视图。

        CREATE VIEW S_G(Sno,Gavg) AS SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno;
      • 不指定属性列。

        CREATE VIEW F_Student(F_Sno,name,sex,age,dept) AS SELECT * FROM Student WHERE Ssex='女';

        注意:本例中修改基表Student的结构后,Student表与F_Student视图的映象关系被破坏,导致该视图不能正确工作。

  2. 删除视图

    • 语句格式

      DROP VIEW <视图名>[CASCADE];
    • 说明

      • 该语句从数据字典中删除指定的视图定义。

      • 如果该视图上还导出了其他视图,使用CASCADE级联删除语句,把该视图和由它导出的所有视图一起删除。

      • 删除基表时,由该基表导出的所有视图定义都必须显式地使用DROP VIEW语句删除。

    • 示例

      • 删除视图BT_S

        DROP VIEW BT_S;
      • 删除视图IS_S1

        DROP VIEW IS_S1;

        因为IS_S1视图上还导出了IS_S2,因此该语句拒绝执行。 正确的删除:

        DROP VIEW IS_S1 CASCADE;
3.7.2 查询视图
  • 视图定义后,用户就可以像基本表一样对视图进行查询了。

  1. RDBMS实现视图查询的方法——视图消解法

    • 第一步:进行有效性检查。

    • 第二步:转换成等价的对基本表的查询。

    • 第三步:执行修正后的查询。

    • 示例:

      • 在信息系学生的视图中找出年龄小于20岁的学生。

        SELECT Sno,Sage FROM IS_Student WHERE Sage<20;

        IS_Student为定义的视图。 视图消解转换后的查询语句为:

        SELECT Sno,Sage FROM Student WHERE Sdept='IS' AND Sage<20;
      • 查询选修了1号课程的信息系学生。

        SELECT IS_Student.Sno,Sname FROM IS_Student,SC WHERE IS_Student.Sno=SC.Sno AND SC.Cno='1';
  2. 视图消解法的局限

    • 视图消解法有些情况下,视图消解法不能生成正确查询。

    • 示例:

      • S_G视图中查询平均成绩在90分以上的学生学号和平均成绩。语句为:

        SELECT * FROM S_G WHERE Gavg>=90;

        S_G视图的子查询如下:

        SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno;

        结合后形成下列查询语句:

        SELECT Sno,AVG(Grade) FROM SC WHERE AVG(Grade)>=90 GROUP BY Sno; (错误的转换)

        正确的转换:

        SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno HAVING AVG(Grade)>=90;
3.7.3 更新视图
  • 说明:更新视图是指通过视图来插入、删除和数据,因为视图不适宜存储数据,因此对视图的更新操作将通过视图消解,转化为对实际表的更新操作。

  • 注意:为防止在更新视图时出错,定义视图时要加上WITH CHECK OPTION子句。

  • 示例:

    • 将信息系学生视图IS_Student中学号200215122的学生姓名改为“刘辰”。

      UPDATE IS_Student SET Sname='刘辰' WHERE Sno='200215122';

      转换后的语句:

      UPDATE Student SET Sname='刘辰' WHERE Sno=200215122 AND Sdept='IS';
    • 向信息系学生视图中插入一个新的学生记录:200215129赵新20

      INSERT INTO IS_Student VALUES('200215129', '赵新',20);

      转换为对基本表的更新:

      INSERT INTO Student(Sno,Sname,Sage,Sdept) VALUES('200215129','赵新',20,'IS');
    • 删除信息系学生视图IS_Student中学号为200215129的记录。

      DELETE FROM IS_Student WHERE Sno='200215129';

      转换为对基本表的更新:

      DELETE FROM Student WHERE Sno='200215129' AND Sdept='IS';
  • 更新视图的限制:一些视图是不可更新的,因为对这些视图的更新不能唯一地有意义地转换成对相应基本表的更新。

    • 示例:对视图S_G中学号为200215121学生的平均成绩改为90分。

      • 建立视图S_G

        CREATE VIEW S_G (Sno,Gavg) AS SELECT Sno,AVG(Grade) FROM SC GROUP BY Sno;
      • 更新视图S_G

        UPDATE S_G SET Gavg=90 WHERE Sno='200215121';
      • 该更新视图无法转换成对基本表SC的更新,因为平均成绩是计算得出的,系统无法修改各科成绩,使平均成绩到90分。

3.7.4 视图的作用
  1. 视图能够简化用户的操作。

  2. 视图使用户能以多种角度看待同一数据。

  3. 视图对重构数据库提供了一定程度的逻辑独立性。

  4. 视图能够对机密数据提供安全保护。

  5. 适当的利用视图可以更清晰的表达查询。

第4章 数据库安全性

4.1 数据库安全性概述

4.1.1 数据库的不安全因素

  1. 非授权用户对数据库的恶意存取和破坏

    • 一些黑客(Hacker)和犯罪分子在用户存取数据库时猎取用户名和用户口令,然后假冒合法用户偷取、修改甚至破坏用户数据。

    • 数据库管理系统提供的安全措施主要包括用户身份鉴别、存取控制和视图等技术。

  2. 数据库中重要或敏感的数据被泄露

    • 黑客和敌对分子千方百计盗窃数据库中的重要数据,一些机密信息被暴露。

    • 数据库管理系统提供的主要技术有强制存取控制、数据加密存储和加密传输等。

    • 安全要求较高的系统提供审计日志分析。对潜在的威胁提前采取措施加以防范。

  3. 安全环境的脆弱性

    • 数据库的安全性与计算机系统的安全性紧密联系,主要包括计算机硬件、操作系统、网络系统等的安全性。

    • 在计算机安全方面需要建立一套可信(Trusted)计算机系统的概念和标准。

4.1.2 安全标准简介

  1. 安全标准的发展历史

    • 1985年美国国防部(DoD)正式颁布《DoD可信计算机系统评估准则》(简称TCSEC或DoD85)。

    • 不同国家在TCSEC概念上建立了评估准则,例如:

      • 欧洲的信息技术安全评估准则(ITSEC)

      • 加拿大的可信计算机产品评估准则(CTCPEC)

      • 美国的信息技术安全联邦标准(FC)

    • 1993年,CTCPEC、FC、TCSEC和ITSEC联合行动,解决原标准中概念和技术上的差异,称为CC(Common Criteria)项目。

    • 1999年,CC V2.1版被ISO采用为国际标准。

    • 2001年,CC V2.1版被我国采用为国家标准。

    • 目前CC已基本取代了TCSEC,成为评估信息产品安全性的主要标准。

  2. TCSEC标准

    • 标准介绍

      • 1991年4月美国NCSC(国家计算机安全中心)颁布了《可信计算机系统评估标准关于可信数据库系统的解释》(Trusted Database Interpretation,简称TDI)。

      • TDI又称紫皮书,它将TCSEC扩展到数据库管理系统,定义了数据库管理系统的设计与实现中需满足和用以进行安全性级别评估的标准。

    • 安全等级划分

      • TCSEC/TDI从安全策略、责任、保证、文档四个方面来描述安全性级别划分的指标:

        安全级别定义
        A1验证设计(verified design)
        B3安全域(security domains)
        B2结构化保护(structural protection)
        B1标记安全保护(labeled security protection)
        C2受控的存取保护(controlled access protection)
        C1自主安全保护(discretionary security protection)
        D最小保护(minimal protection)
      • 四组(division)七个等级:D、C(C1,C2)、B(B1,B2,B3)、A(A1)。

      • 七个等级按系统可靠或可信程度逐渐增高。

      • 各安全级别之间具有一种偏序向下兼容的关系,即较高安全性级别提供的安全保护要包含较低级别的所有保护要求,同时提供更多或更完善的保护能力。

      • D级:将一切不符合更高标准的系统均归于D组。DOS在安全性方面几乎没有什么专门的机制来保障。

      • C1级:非常初级的自主安全保护。能够实现对用户和数据的分离,进行自主存取控制(DAC),保护或限制用户权限的传播。

      • C2级:安全产品的最低档次。提供受控的存取保护,将C1级的DAC进一步细化,以个人身份注册负责,并实施审计和资源隔离。

      • B1级:标记安全保护。“安全”(Security)或“可信的”(Trusted)产品。对系统的数据加以标记,对标记的主体和客体实施强制存取控制(MAC)、审计等安全机制。

      • B2级:结构化保护。建立形式化的安全策略模型并对系统内的所有主体和客体实施DAC和MAC。

      • B3级:安全域。该级的TCB必须满足访问监控器的要求,审计跟踪能力更强,并提供系统恢复过程。

      • A1级:验证设计。即提供B3级保护的同时给出系统的形式化设计说明和验证以确信各安全保护真正实现。

  3. CC标准

    • CC标准:提出国际公认的表述信息技术安全性的结构,把信息产品的安全要求分为安全功能要求、安全保证要求。

    • CC文本组成

      1. 简介和一般模型:有关术语、基本概念和一般模型以及与评估有关的一些框架。

      2. 安全功能要求:列出了一系列类、子类和组件。11大类、66个子类和135个组件构成。

      3. 安全保证要求:列出了一系列保证类、子类和组件。提出了评估保证级(Evaluation Assurance Level,EAL),从EAL1至EAL7共分为七级。

    • CC评估保证级(EAL)划分

      评估保证级定义TCSEC安全级别(近似相当)
      EAL1功能测试(functionally tested)D
      EAL2结构测试(structurally tested)C1
      EAL3系统地测试和检查(methodically tested and checked)C2
      EAL4系统地设计、测试和复查(methodically designed,tested and reviewed)B1
      EAL5半形式化设计和测试(semiformally designed and tested)B2
      EAL6半形式化验证的设计和测试(semiformally verified design and tested)B3
      EAL7形式化验证的设计和测试(formally verified design and tested)A1

4.2 数据库安全性控制

1. 非法使用数据库的情况

  1. 编写合法程序绕过数据库管理系统及其授权机制。

  2. 直接或编写应用程序执行非授权操作。

  3. 通过多次合法查询数据库从中推导出一些保密数据。

2. 计算机系统的安全模型

  • 计算机系统中安全措施是一级一级层层设置。具体模型如下:

3. 数据库有关的安全性

  • 数据库安全性主要包括:用户身份验证、多层存取控制、审计、视图、数据加密等安全技术。

  • 数据库管理系统安全性控制模型

    • 存取控制流程:

      1. 首先,数据库管理系统对提出SQL访问请求的数据库用户进行身份鉴别,防止不可信用户使用系统。

      2. 然后,在SQL处理层进行自主存取控制和强制存取控制,进一步可以进行推理控制。

      3. 还可以对用户访问行为和系统关键操作进行审计,对异常用户行为进行简单入侵检测。

4.2.1 用户身份鉴别

  1. 用户身份鉴别概念

    • 用户身份鉴别(Identification & Authentication)是指每个用户在系统中都有一个用户标识,每次用户要求进入系统时,由系统核对,通过鉴定后提供数据库管理系统的使用权限。它是系统提供的最外层安全保护措施。

  2. 用户标识组成

    • 用户标识由用户名和用户标识号组成,用户标识号在系统整个生命周期内唯一。

  3. 用户身份鉴别的方法

    1. 静态口令鉴别:静态口令一般由用户自己设定,这些口令是静态不变的。

    2. 动态口令鉴别:口令是动态变化的,每次鉴别时均需使用动态产生的新口令登录数据库管理系统,即采用一次一密的方法。

    3. 生物特征鉴别:通过生物特征进行认证的技术,生物特征如指纹、虹膜和掌纹等。

    4. 智能卡鉴别:智能卡是一种不可复制的硬件,内置集成电路的芯片,具有硬件加密功能。

4.2.2 存取控制

  1. 存取控制机制组成

    • 用户权限定义和合法权检查机制一起组成了数据库管理系统的存取控制子系统。

    • 定义用户权限,并将用户权限登记到数据字典中

      • 权限是指用户对某一数据对象的操作权力。

      • DBMS提供适当的语言来定义用户权限,存放在数据字典中,称做安全规则或授权规则。

    • 合法权限检查

      • 用户发出存取数据库操作请求。

      • DBMS查找数据字典,进行合法权限检查。

  2. 常用存取控制方法

    1. 自主存取控制

    • 自主存取控制(Discretionary Access Control,简称DAC)中用户对不同的数据对象有不同的存取权限,不同的用户对同一对象也有不同的权限,用户可将其拥有的存取权限转授给其他用户。

    • C2级的数据库管理系统支持自主存取控制。

    1. 强制存取控制

    • 强制存取控制(Mandatory Access Control,简称MAC)中每一个数据对象被标以一定的密级,每一个用户也被授予某一个级别的许可证,对于任意一个对象,只有具有合法许可证的用户才可以存取。

    • B1级的数据库管理系统支持强制存取控制。

    1. 关系数据库系统中存取控制对象权限

    对象类型对象操作类型
    数据库模式
    模式CREATE SCHEMA
    基本表CREATE TABLE,ALTER TABLE
    视图CREATE VIEW
    索引CREATE INDEX
    数据SELECT,INSERT,UPDATE,DELETE,REFERENCES,ALL PRIVILEGES
    属性列SELECT,INSERT,UPDATE,REFERENCES,ALL PRIVILEGES

4.2.3 自主存取控制方法

  • SQL标准的通过GRANT语句和REVOKE语句实现自主存取控制。

4.2.4 授权:授予与回收

  1. GRANT:对指定操作对象的指定操作权限授予指定的用户

    • GRANT语句的一般格式

      GRANT <权限>[,<权限>] …
      ON <对象类型> <对象名>[,<对象类型> <对象名>] …
      TO <用户>[,<用户>] …
      [WITH GRANT OPTION];
    • 说明

      1. 发出GRANT法人可以是数据库管理员、数据库对象创建者(即属主Owner)、拥有该权限的用户。

      2. 接受权限的用户可以是一个或多个具体用户、PUBLIC(即全体用户)。

      3. WITH GRANT OPTION子句:有,表示该权限可以再授予其他用户。没有,表示该权限不可以再授予其他用户。

      4. SQL标准不允许循环授权。

    • 示例

      • 把查询Student表权限授给用户U1。

        GRANT SELECT
        ON TABLE Student
        TO U1;
      • 把对表SC的查询权限授予所有用户。

        GRANT SELECT
        ON TABLE SC
        TO PUBLIC;
      • 把查询Student表和修改学生学号的权限授给用户U4。

        GRANT UPDATE(Sno), SELECT
        ON TABLE Student
        TO U4;
      • 把对表SC的INSERT权限授予U5用户,并允许他再将此权限授予其他用户。

        GRANT INSERT
        ON TABLE SC
        TO U5
        WITH GRANT OPTION;
  2. REVOKE:授予的权限可以由数据库管理员或其他授权者用REVOKE语句收回

    • REVOKE语句的一般格式

      REVOKE <权限>[,<权限>] …
      ON <对象类型> <对象名>[,<对象类型><对象名>]…
      FROM <用户>[,<用户>] …[CASCADE | RESTRICT];
    • 示例

      • 把用户U4修改学生学号的权限收回。

        REVOKE UPDATE(Sno)
        ON TABLE Student
        FROM U4;
      • 收回所有用户对表SC的查询权限。

        REVOKE SELECT
        ON TABLE SC
        FROM PUBLIC;
      • 把用户U5对SC表的INSERT权限收回。

        REVOKE INSERT
        ON TABLE SC
        FROM U5 CASCADE;

4.2.5 数据库角色

  • 数据库角色是指被命名的一组与数据库操作相关的权限,角色是权限的集合。

  • 可以为一组具有相同权限的用户创建一个角色,简化授权的过程

  • SQL中首先用CREATE ROLE语句创建角色,然后用GRANT语句授权,用REVOKE收回授予角色的权限

  1. 角色的创建

    • 格式:CREATE ROLE <角色名>;

  2. 给角色授权

    • 格式:

      GRANT <权限>[,<权限>]…
      ON <对象类型>对象名
      TO <角色>[,<角色>]…;
  3. 将一个角色授予其他的角色或用户

    • 格式:

      GRANT <角色1>[,<角色2>]…
      TO <角色3>[,<用户1>]…
      [WITH ADMIN OPTION];
    • 说明

      1. 该语句把角色授予某用户,或授予另一个角色。

      2. 授予者是角色创建者或拥有在这个角色上的ADMIN OPTION。

      3. 指定了WITH ADMIN OPTION则获得某种权限的角色或用户还可以把这种权限授予其他角色。

  4. 角色权限的收回

    • 格式:

      REVOKE <权限>[,<权限>]…
      ON <对象类型> <对象名>
      FROM <角色>[,<角色>]…;
    • 说明

      1. 用户可以回收角色的权限,从而修改角色拥有的权限。

      2. REVOKE执行者是:角色的创建者、拥有在这个(些)角色上的ADMIN OPTION。

    • 示例

      • 通过角色来实现将一组权限授予一个用户。

        1. 首先创建一个角色R1。

        CREATE ROLE R1;
        1. 然后使用GRANT语句,使角色R1拥有Student表的SELECT、UPDATE、INSERT权限。

        GRANT SELECT, UPDATE, INSERT
        ON TABLE Student
        TO R1;
        1. 将这个角色授予王平,张明,赵玲。使他们具有角色R1所包含的全部权限。

        GRANT R1
        TO 王平,张明,赵玲;
        1. 可以一次性通过R1来回收王平的这3个权限。

        REVOKE R1
        FROM 王平;

4.2.6 强制存取控制方法

  1. 自主存取控制缺点

    • 可能存在数据“无意泄露”的风险。

    • 原因:这种机制仅仅通过对数据的存取权限来进行安全控制,而数据本身并无安全性标记。

    • 解决:对系统控制下的所有主客体实施强制存取控制策略。

  2. 强制存取控制(MAC)

    • 作用:保证更高程度的安全性、用户不能直接感知或进行控制。

    • 适用于对数据有严格而固定密级分类的部门,如军事部门、政府部门

    • 在强制存取控制中实体分类

      1. 主体:主体是系统中的活动实体。包括数据库管理系统所管理的实际用户和代表用户的各进程。

      2. 客体:客体是系统中的被动实体,包括受主体操纵文件、基本表、索引、视图。

    • 敏感度标记(Label)

      • 对于主体和客体,DBMS为它们每个实例(值)指派一个敏感度标记(Label)。

      • 敏感度标记分成若干级别:绝密(Top Secret,TS)、机密(Secret,S)、可信(Confidential,C)、公开(Public,P)。

      • 密级的次序为:TS>=S>=C>=P。

      • 主体的敏感度标记称为许可证级别(Clearance Level)。

      • 客体的敏感度标记称为密级(Classification Level)。

    • 强制存取控制规则

      1. 仅当主体的许可证级别大于或等于客体的密级时,该主体才能读取相应的客体。

      2. 仅当主体的许可证级别小于或等于客体的密级时,该主体才能写相应的客体。

    • 说明

      1. 强制存取控制(MAC)是对数据本身进行密级标记,无论数据如何复制,标记与数据是一个不可分的整体,只有符合密级标记要求的用户才可以操纵数据。

      2. 实现强制存取控制时要首先实现自主存取控制。

      3. 自主存取控制与强制存取控制共同构成数据库管理系统的安全机制。

  3. DAC + MAC安全检查

    • 系统首先进行自主存取控制检查,通过自主存取控制检查的数据对象再由系统进行强制存取控制检查,只有通过强制存取控制检查的数据对象方可存取。

    • DAC 检查

      • SQL语法分析 & 语义检查

      • 继续语义检查

    • MAC 检查

      • 安全检查

4.3 视图机制

  • 视图对数据库安全的作用

    1. 把要保密的数据对无权存取这些数据的用户隐藏起来,对数据提供一定程度的安全保护。

    2. 间接地实现支持存取谓词的用户权限定义。

  • 示例

    • 王平老师只能检索计算机系学生的信息,系主任张明具有检索和增删改计算机系学生信息的所有权限。在数据库系统中可以用视图实现以上功能。

    • 建立计算机系学生的视图,把对该视图的SELECT权限授于王平,把该视图上的所有操作权限授于张明

      1. 第一步:先建立计算机系学生的视图CS_Student。

        CREATE VIEW CS_Student
        AS
        SELECT *
        FROM Student
        WHERE Sdept='CS';
      2. 第二步:在视图上给王平老师授予检索计算机系学生信息的权限。

        GRANT SELECT
        ON CS_Student
        TO 王平;
      3. 第三步:在视图上所有的权限授予系主任张明。

        GRANT ALL PRIVILIGES
        ON CS_Student
        TO 张明;

4.4 审计(Audit)

  1. 什么是审计?

    • 审计日志(Audit Log):启用一个专用的审计日志,将用户对数据库的所有操作记录在上面。

    • 审计员:审计员利用审计日志监控数据库中的各种行为,找出非法存取数据的人、时间和内容。

    • C2以上安全级别的DBMS必须具有审计功能

  2. 审计功能的可选性

    • 审计很费时间和空间。

    • DBA可以根据应用对安全性的要求,灵活地打开或关闭审计功能。

    • 审计功能主要用于安全性要求较高的部门。

  3. 审计事件

    • 服务器事件:审计数据库服务器发生的事件。

    • 系统权限:对系统拥有的结构或模式对象进行操作的审计,要求该操作的权限是通过系统权限获得的。

    • 语句事件:对SQL语句,如DDL、DML、DQL及DCL语句的审计。

    • 模式对象事件:对特定模式对象上进行的SELECT或DML操作的审计。

  4. 审计功能

    • 基本功能:提供多种审计查阅方式。

    • 多套审计规则:一般在初始化设定。

    • 提供审计分析和报表功能

    • 审计日志管理功能

      1. 防止审计员误删审计记录,审计日志必须先转储后删除。

      2. 对转储的审计记录文件提供完整性和保密性保护。

      3. 只允许审计员查阅和转储审计记录,不允许任何用户新增和修改审计记录等。

    • 提供查询审计设置及审计记录信息的专门视图

  5. 审计分类

    • 用户级审计:任何用户可设置的审计,主要是用户针对自己创建的数据库表和视图进行审计。

    • 系统级审计:只能由数据库管理员设置,监测成功或失败的登录要求、监测授权和收回操作以及其他数据库级权限下的操作。

  6. AUDIT语句和NOAUDIT语句

    • AUDIT语句设置审计功能,NOAUDIT语句取消审计功能。

    • 示例

      • 对修改SC表结构或修改SC表数据的操作进行审计。

        AUDIT ALTER,UPDATE
        ON SC;
      • 取消对SC表的一切审计。

        NOAUDIT ALTER,UPDATE
        ON SC;
    • 说明

      1. 审计设置和审计日志一般存储在数据字典中。

      2. 必须打开审计开关,系统参数audit_trail设为true,才能在系统表SYS_AUDITTRAIL中看到审计信息。

      3. 数据库安全审计系统提供一种事后检查的安全机制。

4.5 数据加密

  • 数据加密是防止数据库中数据在存储和传输中失密的有效手段。

  • 加密的基本思想是根据一定的算法将原始数据—明文(Plain text)变换为不可直接识别的格式—密文(Cipher text)。

  • 数据加密包括存储加密和传输加密

  1. 存储加密

    1. 透明存储加密

    • 内核级加密保护方式,对用户完全透明。

    • 将数据在写到磁盘时对数据进行加密,授权用户读取数据时再对其进行解密。

    • 数据库的应用程序不需要做任何修改,只需在创建表语句中说明需加密的字段即可。

    • 内核级加密方法:性能较好,安全完备性较高。

    1. 非透明存储加密

    • 通过多个加密函数实现。

  2. 传输加密

    1. 链路加密

    • 在链路层进行加密。

    • 传输信息由报头和报文两部分组成,报文和报头均加密。

    1. 端到端加密

    • 在发送端加密,接收端解密。

    • 只加密报文不加密报头。

    • 所需密码设备数量相对较少,容易被非法监听者发现并从中获取敏感信息。

    • 数据库管理系统可信传输示意图

      1. 确认通信双方端点的可靠性

      • 采用基于数字证书的服务器和客户端认证方式。通信时均首先向对方提供己方证书,然后使用本地的CA信任列表和证书撤销列表对接收到的对方证书进行验证。

      1. 协商加密算法和密钥

      • 确认双方端点的可靠性后,通信双方协商本次会话的加密算法与密钥。

      1. 可信数据传输

      • 数据在被发送前用某一组特定的密钥进行加密和消息摘要计算,以密文形式在网络上传输。数据被接收的时候,需用相同一组特定的密钥进行解密和摘要计算。

4.6 其他安全性保护

  1. 推理控制

    • 处理强制存取控制未解决的问题,避免用户利用能够访问的数据推知更高密级的数据。

    • 常用方法:基于函数依赖的推理控制、基于敏感关联的推理控制。

  2. 隐蔽信道

    • 处理强制存取控制未解决的问题。

  3. 数据隐私保护

    • 描述个人控制其不愿他人知道或他人不便知道的个人数据的能力。主要用于数据收集存储处理和数据发布等各个阶段。

4.7 小结

  1. 数据库管理系统是管理数据的核心,必须有一套完整而有效的安全性机制

  2. 数据库管理系统的主要安全措施有

    1. 用户身份鉴别;

    2. 自主存取控制和强制存取控制技术;

    3. 视图技术和审计技术;

    4. 数据加密存储和加密传输。

第5章 数据库完整性

1. 数据库完整性介绍

  • 数据库的完整性是指数据的正确性和相容性。

    • 数据的正确性:数据是符合现实世界语义,反映了当前实际状况的。

    • 数据的相容性:数据库同一对象在不同关系表中的数据是符合逻辑的。

  • 示例

    • 学生的学号必须唯一。

    • 性别只能是男或女。

    • 本科学生年龄的取值范围为14~50的整数。

    • 学生所选的课程必须是学校开设的课程。

    • 学生所在的院系必须是学校已成立的院系等。

2. 数据的完整性和安全性的概念

  1. 数据的完整性

    • 防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据。

    • 防范对象:不合语义的、不正确的数据。

  2. 数据的安全性

    • 保护数据库防止恶意的破坏和非法的存取。

    • 防范对象:非法用户和非法操作。

3. 数据库在完整性方面应具备的功能

  1. 提供定义完整性约束条件的机制

    • 完整性约束条件也称为完整性规则,是数据库中的数据必须满足的语义约束条件。

    • SQL标准通过数据定义语言来描述完整性,包括关系模型的实体完整性、参照完整性和用户定义完整性。

  2. 提供完整性检查的方法

    • 数据库管理系统中检查数据是否满足完整性约束条件的机制称为完整性检查。

    • 一般在INSERTUPDATEDELETE语句执行后开始检查,也可以在事务提交时检查。

  3. 违约处理

    • 数据库管理系统若发现用户的操作违背了完整性约束条件,就采取拒绝(NO ACTION)执行该操作或级连(CASCADE)执行其他操作等方式保证完整性。

5.1 实体完整性

5.1.1 实体完整性定义

  1. 关系模型的实体完整性

    • 设置主码,让每条记录是相互可区分的,SQL中在CREATE TABLE中用PRIMARY KEY定义。

  2. 主码是单属性构成的有两种说明方法

    • 定义为列级约束条件。

    • 定义为表级约束条件。

  3. 主码是多属性的只能有一种说明方法

    • 定义为表级约束条件。

  • 示例

    • Student表中的Sno属性定义为主码。

      1. 在列级定义主码

        CREATE TABLE Student
        (Sno CHAR(9) PRIMARY KEY, /*在列级定义主码*/
        Sname CHAR(20) NOT NULL,
        Ssex CHAR(2),
        Sage SMALLINT,
        Sdept CHAR(20)
        );
      2. 在表级定义主码

        CREATE TABLE Student
        (Sno CHAR(9),
        Sname CHAR(20) NOT NULL,
        Ssex CHAR(2),
        Sage SMALLINT,
        Sdept CHAR(20),
        PRIMARY KEY (Sno) /*在表级定义主码*/
        );
      3. 只能在表级定义主码

        CREATE TABLE SC
        (Sno CHAR(9) NOT NULL,
        Cno CHAR(4) NOT NULL,
        Grade SMALLINT,
        PRIMARY KEY (Sno,Cno) /*只能在表级定义主码*/
        );

5.1.2 实体完整性检查和违约处理

  1. 完整性检查的内容

    • 关系数据库管理系统按照实体完整性规则自动进行检查。检查内容主要包括:

      1. 检查主码值是否唯一,如果不唯一则拒绝插入或修改。

      2. 检查主码的各个属性是否为空,只要有一个为空就拒绝插入或修改。

  2. 检查主码值方法

    • 检查记录中主码值是否唯一的一种方法是进行全表扫描。即依次判断表中每一条记录的主码值与将插入记录上的主码值(或者修改的新主码值)是否相同。

    • 说明

      1. 全表扫描的缺点是十分耗时。

      2. 为避免对基本表进行全表扫描,RDBMS核心一般都在主码上自动建立一个索引。例如:B+树索引。

5.2 参照完整性

5.2.1 参照完整性定义

  • 参照完整性定义:在CREATE TABLE中用FOREIGN KEY定义哪些列为外码,用REFERENCES短语指明这些外码参照哪些表的主码。

  • 示例

    • 关系SC中(SnoCno)是主码。SnoCno分别参照Student表的主码和Course表的主码。

    • CREATE TABLE SC
      (Sno CHAR(9) NOT NULL,
      Cno CHAR(4) NOT NULL,
      Grade SMALLINT,
      PRIMARY KEY (Sno, Cno), /*在表级定义实体完整性*/
      FOREIGN KEY (Sno) REFERENCES Student(Sno),
      /*在表级定义参照完整性*/
      FOREIGN KEY (Cno) REFERENCES Course(Cno)
      /*在表级定义参照完整性*/
      );

5.2.2 参照完整性检查和违约处理

  • 一个参照完整性将两个表中的相应元组联系起来,对被参照表和参照表进行增删改操作时都有可能破坏参照完整性,必须进行完整性检查。

  • 示例

    • 对表SCStudent有四种可能破坏参照完整性的情况。

  • 参照完整性违约处理规则

    1. 拒绝(NO ACTION)执行。不允许该操作执行。该策略一般设置为默认策略。

    2. 级联(CASCADE)操作。当删除或修改被参照表(Student)的一个元组造成了与参照表(SC)的不一致,则删除或修改参照表中的所有造成不一致的元组。

    3. 设置为空值(SET-NULL)。当删除或修改被参照表的一个元组时造成了不一致,则将参照表中的所有造成不一致的元组的对应属性设置为空值。

  • 示例

    • 有下面2个关系:

      • 学生(学号,姓名,性别,专业号,年龄)

      • 专业(专业号,专业名)

      • 假设专业表中专业号为12的元组被删除,按照设置为空值的策略,就要把学生表中专业号为12的所有元组的专业号设置为空值。

      • 对应语义:某个专业删除了,该专业的所有学生专业未定,等待重新分配专业。

    • 显式说明参照完整性的违约处理示例

      CREATE TABLE SC
      (Sno CHAR(9) NOT NULL,
      Cno CHAR(4) NOT NULL,
      Grade SMALLINT,
      PRIMARY KEY(Sno,Cno),
      FOREIGN KEY (Sno) REFERENCES Student(Sno)
      ON DELETE CASCADE /*级联删除SC表中相应的元组*/
      ON UPDATE CASCADE, /*级联更新SC表中相应的元组*/
      FOREIGN KEY (Cno) REFERENCES Course(Cno)
      ON DELETE NO ACTION
      /*当删除course表中的元组造成了与SC表不一致时拒绝删除*/
      ON UPDATE CASCADE
      /*当更新course表中的cno时,级联更新SC表中相应的元组*/
      );

5.3 用户定义的完整性

  • 用户定义的完整性:针对某一具体应用的数据必须满足的语义要求。用户定义的完整性由关系数据库管理系统提供了定义和检验用户定义完整性的机制,不必由应用程序承担。

5.3.1 属性上的约束条件

  1. 属性上约束条件的定义

    • CREATE TABLE时定义属性上的约束条件包括:列值非空(NOT NULL)、列值唯一(UNIQUE)、检查列值是否满足一个条件表达式(CHECK)。

    • 示例

      • 不允许取空值:

        • 在定义SC表时说明SnoCnoGrade属性不允许空值。

          CREATE TABLE SC
          (Sno CHAR(9) NOT NULL,
          Cno CHAR(4) NOT NULL,
          Grade SMALLINT NOT NULL,
          PRIMARY KEY (Sno, Cno),
          ...
          /* 如果在表级定义实体完整性,隐含了Sno,Cno不允许取
          空值,则在列级不允许取空值的定义 可以不写 * /
          );
      • 列值唯一:

        • 建立部门表DEPT,要求部门名称Dname列取值唯一,部门编号Deptno列为主码。

          CREATE TABLE DEPT
          (Deptno NUMERIC(2),
          Dname CHAR(9) UNIQUE NOT NULL,
          /*要求Dname列值唯一, 并且不能取空值*/
          Location CHAR(10),
          PRIMARY KEY (Deptno)
          );
      • CHECK短语指定列值应该满足的条件:

        • Student表的Ssex只允许取“男”或“女”。

          CREATE TABLE Student
          (Sno CHAR(9) PRIMARY KEY,
          Sname CHAR(8) NOT NULL,
          Ssex CHAR(2) CHECK (Ssex IN('男','女')),
          /*性别属性Ssex只允许取'男'或'女' */
          Sage SMALLINT,
          Sdept CHAR(20)
          );
        • SC表的Grade的值应该在0和100之间。

          CREATE TABLE SC
          (Sno CHAR(9),
          Cno CHAR(4),
          Grade SMALLINT CHECK (Grade>=0 AND Grade <=100),
          /*Grade取值范围是0到100*/
          PRIMARY KEY (Sno,Cno),
          FOREIGN KEY (Sno) REFERENCES Student(Sno),
          FOREIGN KEY (Cno) REFERENCES Course(Cno)
          );
  2. 属性上的约束条件检查和违约处理

    • 插入元组或修改属性的值时,关系数据库管理系统检查属性上的约束条件是否被满足,如果不满足则操作被拒绝执行。

5.3.2 元组上的约束条件

  1. 元组上约束条件的定义

    • CREATE TABLE时可以用CHECK短语定义元组上的约束条件,即元组级的限制。

    • 元组级的限制可以设置不同属性之间的取值的相互约束条件。

    • 示例

      • 当学生的性别是男时,其名字不能以Ms.打头。

        CREATE TABLE Student
        (Sno CHAR(9),
        Sname CHAR(8) NOT NULL,
        Ssex CHAR(2),
        Sage SMALLINT,
        Sdept CHAR(20),
        PRIMARY KEY (Sno),
        CHECK (Ssex='女' OR Sname NOT LIKE 'Ms.%')
        /*定义了元组中Sname和 Ssex两个属性值之间的约束条件*/
        );
        • 性别是女性的元组都能通过该项检查,因为Ssex='女'成立;当性别是男性时,要通过检查则名字一定不能以Ms.打头。

  2. 元组上约束条件检查和违约处理

    • 插入元组或修改属性的值时,关系数据库管理系统检查元组上的约束条件是否被满足,如果不满足则操作被拒绝执行。

5.4 完整性约束命名子句

  • 格式CONSTRAINT <完整性约束条件名> <完整性约束条件>

    • <完整性约束条件>包括NOT NULLUNIQUEPRIMARY KEY短语、FOREIGN KEY短语、CHECK短语等。

  • 示例

    • 建立学生登记表Student,要求学号在90000~99999之间,姓名不能取空值,年龄小于30,性别只能是“男”或“女”。

      CREATE TABLE Student
      (Sno NUMERIC(6)
      CONSTRAINT C1 CHECK (Sno BETWEEN 90000 AND 99999),
      Sname CHAR(20) CONSTRAINT C2 NOT NULL,
      Sage NUMERIC(3) CONSTRAINT C3 CHECK (Sage < 30),
      Ssex CHAR(2)
      CONSTRAINT C4 CHECK (Ssex IN ( '男','女')),
      CONSTRAINT StudentKey PRIMARY KEY(Sno) );
      • Student表上建立了5个约束条件,包括主码约束(命名为StudentKey)以及C1C2C3C4四个列级约束。

  1. 修改表中的完整性限制

    • 使用ALTER TABLE语句修改表中的完整性限制。

    • 示例

      • 去掉例题中对性别的限制。

        ALTER TABLE Student
        DROP CONSTRAINT C4;
      • 修改表Student中的约束条件,要求学号改为在900000 ~ 999999之间,年龄由小于30改为小于40。

        • 可以先删除原来的约束条件,再增加新的约束条件。

          ALTER TABLE Student
          DROP CONSTRAINT C1;
          ALTER TABLE Student
          ADD CONSTRAINT C1 CHECK (Sno BETWEEN 900000 AND 999999),
          ALTER TABLE Student
          DROP CONSTRAINT C3;
          ALTER TABLE Student
          ADD CONSTRAINT C3 CHECK(Sage < 40);

5.5 域中的完整性限制

  • 是一组具有相同数据类型的值的集合,即属性的取值范围。

  • SQL可以用CREATE DOMAIN语句建立一个域以及域应该满足的完整性约束条件,然后用域定义属性。

  • 示例

    • 建立一个性别域,并声明性别域的取值范围。

      CREATE DOMAIN GenderDomain CHAR(2)
      CHECK(VALUE IN('男','女'));
      • 可以用GenderDomain定义性别属性:Ssex GenderDomain

    • 建立一个性别域GenderDomain,并对其中的限制命名。

      CREATE DOMAIN GenderDomain CHAR(2)
      CONSTRAINT GD CHECK(VALUE IN('男','女'));
    • 删除域GenderDomain的限制条件GD

      ALTER DOMAIN GenderDomain
      DROP CONSTRAINT GD;
    • 在域GenderDomain上增加性别的限制条件GDD

      ALTER DOMAIN GenderDomain
      ADD CONSTRAINT GDD CHECK(VALUE IN('1','0'));
      • 通过以上两个例子可以把属性的取值范围由('男','女')改为('1','0')

5.6 断言

  1. 创建断言的语句格式

    • CREATE ASSERTION<断言名><CHECK 子句>

    • 每个断言都被赋予一个名字,<CHECK 子句>中的约束条件与WHERE子句的条件表达式类似。

  2. 示例

    • 限制数据库课程最多60名学生选修。

      CREATE ASSERTION ASSE_SC_DB_NUM
      CHECK (60 >= (select count(*)
      /*此断言的谓词涉及聚集操作count的SQL语句*/
      From Course,SC
      Where SC.Cno=Course.Cno and Course.Cname ='数据库')
      );
    • 限制每一门课程最多60名学生选修。

      CREATE ASSERTION ASSE_SC_CNUM1
      CHECK(60 >= ALL (SELECT count(*)
      FROM SC
      GROUP by cno)
      );
      /*此断言的谓词,涉及聚集操作count 和分组函数group by
      的SQL语句*/
    • 限制每个学期每一门课程最多60名学生选修。

      • 首先需要修改SC表的模式,增加一个“学期(TERM)”属性。

        ALTER TABLE SC ADD TERM DATE;
      • 然后,定义断言:

        CREATE ASSERTION ASSE_SC_CNUM2
        CHECK(60 >= ALL (SELECT count(*)
        FROM SC
        GROUP by cno,TERM)
        );
  3. 删除断言

    • 语句格式为:DROP ASSERTION <断言名>;

    • 如果断言很复杂,则系统在检测和维护断言的开销较高,这是在使用断言时应该注意的。

5.7 触发器

  • 触发器(Trigger)定义:触发器是用户定义在关系表上的一类由事件驱动的特殊过程。

    • 触发器保存在数据库服务器中。

    • 任何用户对表的增、删、改操作均由服务器自动激活相应的触发器。

    • 触发器可以实施更为复杂的检查和操作,具有更精细和更强大的数据控制能力。

5.7.1 定义触发器

  • 触发器又叫做事件-条件-动作(event-condition-action)规则。

  1. 语句格式为

    CREATE TRIGGER <触发器名>
    {BEFORE | AFTER} <触发事件> ON <表名>
    REFERENCING NEW|OLD ROW AS<变量>
    FOR EACH{ROW | STATEMENT}
    [WHEN <触发条件>]<触发动作体>
    • 说明:当特定的系统事件发生时,对规则的条件进行检查,如果条件成立则执行规则中动作,否则不执行该动作。规则中的动作体可以很复杂,通常是一段SQL存储过程。

  2. 定义触发器的语法说明

    1. 表的拥有者才可以在表上创建触发器。

    2. 触发器名

    • 触发器名可以包含模式名,也可以不包含模式名。

    • 同一模式下,触发器名必须是唯一的。

    • 触发器名和表名必须在同一模式下。

    1. 表名

    • 触发器只能定义在基本表上,不能定义在视图上。

    • 当基本表的数据发生变化时,将激活定义在该表上相应触发事件的触发器。

    1. 触发事件

    2. INSERTDELETEUPDATE也可以是这几个事件的组合。

    3. UPDATE OF<触发列,…>,即进一步指明修改哪些列时激活触发器。

    4. AFTER/BEFORE是触发的时机。

    - `AFTER`表示在触发事件的操作执行之后激活触发器。
    - `BEFORE`表示在触发事件的操作执行之前激活触发器。
    1. 触发器类型

    • 行级触发器(FOR EACH ROW)和语句级触发器(FOR EACH STATEMENT)。

    • 示例

      • 在上例建立TEACHER时,表上创建一个AFTER UPDATE触发器,触发事件是UPDATE语句:

        • UPDATE TEACHER SET Deptno=5;

        • 假设表TEACHER有1000行:

          • 如果是语句级触发器,那么执行完该语句后,触发动作只发生一次。

          • 如果是行级触发器,触发动作将执行1000次。

    1. 触发条件

    • 触发器被激活时,只有当触发条件为真时触发动作体才执行;否则触发动作体不执行。

    • 如果省略WHEN触发条件,则触发动作体在触发器激活后立即执行。

    1. 触发动作体

    2. 触发动作体可以是一个匿名PL/SQL过程块,也可以是对已创建存储过程的调用。

    3. 如果是行级触发器,用户都可以在过程体中使用NEWOLD引用事件之后的新值和事件之前的旧值。

    4. 如果是语句级触发器,则不能在触发动作体中使用NEWOLD进行引用。

    5. 如果触发动作体执行失败,激活触发器的事件就会终止执行,触发器的目标表或触发器可能影响的其他对象不发生任何变化。

    • 注意:不同的RDBMS产品触发器语法各不相同。

    • 示例

      • 当对表SCGrade属性进行修改时,若分数增加了10%则将此次操作记录到下面表中:

        • SC_U(Sno,Cno,Oldgrade,Newgrade)

        • 其中Oldgrade是修改前的分数,Newgrade是修改后的分数。

        • 设计触发器:

          CREATE TRIGGER SC_T
          AFTER UPDATE OF Grade ON SC
          REFERENCING
          OLD row AS OldTuple,
          NEW row AS NewTuple
          FOR EACH ROW
          WHEN (NewTuple.Grade >= 1.1*OldTuple.Grade)
          INSERT INTO SC_U(Sno,Cno,OldGrade,NewGrade)
          VALUES(OldTuple.Sno,OldTuple.Cno,OldTuple.Grade,
          NewTuple.Grade)
      • 将每次对表Student的插入操作所增加的学生个数记录到表StudentInsertLog中。

        CREATE TRIGGER Student_Count
        AFTER INSERT ON Student
        REFERENCING
        NEW TABLE AS DELTA
        FOR EACH STATEMENT
        INSERT INTO StudentInsertLog (Numbers)
        SELECT COUNT(*) FROM DELTA
      • 定义BEFORE行级触发器,为教师表Teacher定义完整性,“教授工资不得低于4000元,如果低于4000元,自动改为4000元”。

        CREATE TRIGGER Insert_Or_Update_Sal
        BEFORE INSERT OR UPDATE ON Teacher
        REFERENCING NEW row AS newTuple
        FOR EACH ROW /*行级触发器*/
        BEGIN /*定义触发动作体,是PL/SQL过程块*/
        IF (newTuple.Job='教授') AND (newTuple.Sal < 4000)
        THEN newTuple.Sal:=4000;
        END IF;
        END;

5.7.2 激活触发器

  • 触发器的执行,是由触发事件激活的,并由数据库服务器自动执行。

  • 一个数据表上可能定义了多个触发器,遵循如下的执行顺序:

    1. 执行该表上的BEFORE触发器。

    2. 激活触发器的SQL语句。

    3. 执行该表上的AFTER触发器。

5.7.3 删除触发器

  • 删除触发器的SQL语法:

    DROP TRIGGER <触发器名> ON <表名>;
  • 触发器必须是一个已经创建的触发器,并且只能由具有相应权限的用户删除。

5.8 小结

  1. 数据库的完整性是为了保证数据库中存储的数据是正确的。

    • 最重要的完整性是实体完整性和参照完整性。

  2. 完整性定义一般由SQL的数据定义语言完成。目前数据库提供了完整性的定义和检查。

  3. 违背完整性约束条件时RDBMS一般采取默认动作,如拒绝执行。

  4. 触发器是保证数据库完整性的一个重要的方法。

第6章 关系数据库理论

6.1 问题的提出

1. 关系模式的表示

关系模式由五部分组成,是一个五元组:R(U,D,DOM,F)

  • R:关系名,是符号化的元组语义。

  • U:一组属性。

  • D:属性组U中的属性所来自的域。

  • DOM:属性到域的映射。

  • F:属性组U上的一组数据依赖。

说明

  • 由于D、DOM与模式设计关系不大,因此在本章中把关系模式看作一个三元组:R<U,F>

  • 当且仅当U上的一个关系r满足F时,r称为关系模式R<U,F>的一个关系。

  • 作为二维表,关系要符合一个最基本的条件:每个分量必须是不可分开的数据项。满足了这个条件的关系模式就属于第一范式(1NF)

2. 数据依赖

数据依赖是一个关系内部属性与属性之间的一种约束关系,是通过属性间值的相等与否体现出来的数据间相互联系。主要类型包括:

  • 函数依赖(Functional Dependency,简记为FD)。

  • 多值依赖(Multi-Valued Dependency,简记为MVD)。

3. 函数依赖在现实生活中的体现

例1:描述一个学生关系,可以有学号、姓名、系名等属性。

  • 一个学号只对应一个学生,一个学生只在一个系中学习。

  • “学号”确定后,学生的姓名及所在系的值就被唯一确定。

  • 记作:Sno→Sname,Sno→Sdept

例2:建立一个描述学校教务的数据库,涉及的对象包括:

  • 学生的学号(Sno)、所在系(Sdept)、系主任姓名(Mname)、课程号(Cno)、成绩(Grade)。

  • 假设学校教务的数据库模式用一个单一的关系模式Student来表示,则该关系模式的属性集合为:U={Sno,Sdept,Mname,Cno,Grade}

  • 现实世界的已知事实(语义):

    • 一个系有若干学生,但一个学生只属于一个系。

    • 一个系只有一名(正职)负责人。

    • 一个学生可以选修多门课程,每门课程有若干学生选修。

    • 每个学生学习每一门课程有一个成绩。

  • 由此可得到属性组U上的一组函数依赖F:

    • F={Sno→Sdept, Sdept→Mname, (Sno,Cno)→Grade}

4. 函数依赖存在的问题

关系模式Student<U,F>中存在的问题:

  • 数据冗余:浪费大量的存储空间,例如系主任的姓名重复出现。

  • 更新异常:数据冗余导致更新数据时维护数据完整性代价大。

  • 插入异常:如果一个系刚成立,尚无学生,则无法把这个系及其系主任的信息存入数据库。

  • 删除异常:如果某个系的学生毕业了,则在删除该系学生信息的同时,把这个系及其系主任的信息也丢掉了。

说明

  • Student关系模式不是一个好的模式。一个“好”的模式应当不会发生插入异常、删除异常和更新异常,数据冗余应尽量少。

  • 存在以上问题的原因是由存在于模式中的某些数据依赖引起的。

  • 解决方法是用规范化理论改造关系模式来消除其中不合适的依赖。

5. 函数依赖的解决方式

将单一的模式分成三个关系模式:

  • S(Sno,Sdept,Sno→Sdept)

  • SC(Sno,Cno,Grade,(Sno,Cno)→Grade)

  • DEPT(Sdept,Mname,Sdept→Mname)

  • 这三个模式都不会发生插入异常、删除异常的问题,数据的冗余也得到了控制。

6.2 规范化

6.2.1 函数依赖

定义1:设R(U)是属性集U上的关系模式,X、Y是U的子集。若对于R(U)的任意一个可能的关系r,r中不可能存在两个元组在X上的属性值相等,而在Y上的属性值不等,则称“X函数确定Y”或“Y函数依赖于X”,记作X→Y。

:Student(Sno,Sname,Ssex,Sage,Sdept)。

  • 假设不允许重名,则有:

    • Sno→Ssex,Sno→Sage,Sno→Sdept,Sno←→Sname。

    • Sname→Ssex,Sname→Sage,Sname→Sdept。

    • 但Ssex Sage,Ssex Sdept。

术语和记号

  • X→Y,但Y X则称X→Y是非平凡的函数依赖。

  • X→Y,但Y X则称X→Y是平凡的函数依赖。

  • 若X→Y,则X称为这个函数依赖的决定属性组,也称为决定因素。

  • 若X→Y,并且Y→X,则记为X←→Y。

  • 若Y不函数依赖于X,则记为X Y。

定义2:在R(U)中,如果X→Y,并且对于X的任何一个真子集X',都有X' Y,则称Y对X完全函数依赖,记作X → Y;若X→Y,但Y不完全函数依赖于X,则称Y对X部分函数依赖,记作X → Y。

:在关系SC(Sno,Cno,Grade)中,

  • 由于:Sno Grade,Cno Grade,

  • 因此:(Sno,Cno) → Grade

  • (Sno,Cno) → Sno

  • (Sno,Cno) → Cno

定义3:在R(U)中,如果X→Y(Y X),Y X,Y→Z,Z Y,则称Z对X传递函数依赖(transitive functional dependency)。记为:X → Z。

注意:如果Y→X,即X←→Y,则Z直接依赖于X,而不是传递函数依赖。

:在关系Std(Sno,Sdept,Mname)中,有Sno→Sdept,Sdept→Mname,Mname传递函数依赖于Sno。

6.2.2 码

定义4:设K为R<U,F>中的属性或属性组合。若K U,则K称为R的一个候选码(Candidate Key)。如果U部分函数依赖于K,即K U,则K称为超码(Surpkey)。候选码是最小的超码,即K的任意一个真子集都不是候选码。若关系模式R有多个候选码,则选定其中的一个做为主码(Primary key)。

主属性与非主属性

  • 主属性(Prime attribute):包含在任何一个候选码中的属性。

  • 非主属性(Nonprime attribute):不包含在任何码中的属性。

  • 全码:整个属性组是码,称为全码(All-key)。

  • S(Sno,Sdept,Sage),单个属性Sno是码。

  • SC(Sno,Cno,Grade)中,(Sno,Cno)是码。

定义5:关系模式R中属性或属性组X并非R的码,但X是另一个关系模式的码,则称X是R的外部码(Foreign key)也称外码。

:SC(Sno,Cno,Grade)中,Sno不是码,Sno是S(Sno,Sdept,Sage)的码,则Sno是SC的外码。

主码与外部码:主码与外部码一起提供了表示关系间联系的手段。

6.2.3 范式

范式是符合某一种级别的关系模式的集合。关系数据库中的关系必须满足一定的要求,满足不同程度要求的为不同范式。

  • 第一范式(1NF)

  • 第二范式(2NF)

  • 第三范式(3NF)

  • BC范式(BCNF)

  • 第四范式(4NF)

  • 第五范式(5NF)

各种范式之间存在联系:5NF ⊆ 4NF ⊆ BCNF ⊆ 3NF ⊆ 2NF ⊆ 1NF

某一关系模式R为第n范式,可简记为R∈nNF。

规范化:是指一个低一级范式的关系模式,通过模式分解转换为若干个高一级范式的关系模式集合的过程。

6.2.4 2NF

定义6:若关系模式R∈1NF,并且每一个非主属性都完全函数依赖于任何一个候选码,则R∈2NF。

:S-L-C(Sno,Sdept,Sloc,Cno,Grade),Sloc为学生的住处,并且每个系的学生住在同一个地方。S-L-C的码为(Sno,Cno)。

  • 函数依赖有:

    • (Sno,Cno) → Grade

    • Sno→Sdept,(Sno,Cno) → Sdept

    • Sno→Sloc,(Sno,Cno) → Sloc

    • Sdept→Sloc

  • 函数依赖关系如下:

    • 非主属性Sdept、Sloc并不完全依赖于码。

  • 关系模式S-L-C不属于2NF。

一个关系模式不属于2NF,会产生以下问题:

  • 插入异常:如果插入一个新学生,但该生未选课,即该生无Cno,由于插入元组时,必须给定码值,因此插入失败。

  • 删除异常:如果S4只选了一门课C3,现在他不再选这门课,则删除C3后,整个元组的其他信息也被删除了。

  • 修改复杂:如果一个学生选了多门课,则Sdept,Sloc被存储了多次。如果该生转系,则需要修改所有相关的Sdept和Sloc,造成修改的复杂化。

出现这种问题的原因:

  • 例子中有两类非主属性:一类如Grade,它对码完全函数依赖,另一类如Sdept、Sloc,它们对码不是完全函数依赖。

解决方法:

  • 用投影分解把关系模式S-L-C分解成两个关系模式。

    • SC(Sno,Cno,Grade)。

    • S-L(Sno,Sdept,Sloc)。

  • SC中的函数依赖:SC的码为(Sno,Cno),SL的码为Sno,这样使得非主属性对码都是完全函数依赖了。

6.2.5 3NF

定义7:设关系模式R<U,F>∈1NF,若R中不存在这样的码X、属性组Y及非主属性Z(Z Y),使得X→Y,Y→Z成立,Y X不成立,则称R<U,F>∈3NF。

:SC没有传递依赖,因此SC∈3NF。

S-L中Sno→Sdept(Sdept Sno),Sdept→Sloc, 可得Sno传递Sloc。 解决的办法是将S-L分解成:

  • S-D(Sno,Sdept)∈3NF。

  • D-L(Sdept,Sloc)∈3NF。

6.2.6 BCNF

BCNF(Boyce Codd Normal Form)由Boyce和Codd提出,比3NF更进了一步。通常认为BCNF是修正的第三范式,有时也称为扩充的第三范式。

定义8:设关系模式R<U,F>∈1NF,若X→Y且Y X时X必含有码,则R<U,F>∈BCNF。

换言之,在关系模式R<U,F>中,如果每一个决定属性集都包含候选码,则R∈BCNF。

BCNF的关系模式所具有的性质:

  1. 所有非主属性都完全函数依赖于每个候选码。

  2. 所有主属性都完全函数依赖于每个不包含它的候选码。

  3. 没有任何属性完全函数依赖于非码的任何一组属性。

如果一个关系数据库中的所有关系模式都属于BCNF,那么在函数依赖范畴内,它已实现了模式的彻底分解,达到了最高的规范化程度,消除了插入异常和删除异常。

例1:考察关系模式C(Cno,Cname,Pcno),它只有一个码Cno,没有任何属性对Cno部分依赖或传递依赖,所以C∈3NF。同时C中Cno是唯一的决定因素,所以C∈BCNF。

例2:关系模式S(Sno,Sname,Sdept,Sage),假定Sname也具有唯一性,那么S就有两个码,这两个码都由单个属性组成,彼此不相交。其他属性不存在对码的传递依赖与部分依赖,所以S∈3NF。同时S中除Sno,Sname外没有其他决定因素,所以S也属于BCNF。

例3:关系模式SJP(S,J,P)中,S是学生,J表示课程,P表示名次。每一个学生选修每门课程的成绩有一定的名次,每门课程中每一名次只有一个学生(即没有并列名次)。

  • 由语义可得到函数依赖:(S,J)→P;(J,P)→S,因此(S,J)与(J,P)都可以作为候选码。

  • 关系模式中没有属性对码传递依赖或部分依赖,故SJP∈3NF。

  • 除(S,J)与(J,P)以外没有其他决定因素,所以SJP∈BCNF。

例4:关系模式STJ(S,T,J)中,S表示学生,T表示教师,J表示课程。每一教师只教一门课。每门课有若干教师,某一学生选定某门课,就对应一个固定的教师。

  • 由语义可得到函数依赖:(S,J)→T;(S,T)→J;T→J。

  • 因为没有任何非主属性对码传递依赖或部分依赖,所以STJ∈3NF。

  • 因为T是决定因素,而T不包含码,所以STJ∉BCNF关系。

说明

  • 对于不是BCNF的关系模式,仍然存在不合适的地方。非BCNF的关系模式也可以通过分解成为BCNF。例如,STJ可分解为ST(S,T)与TJ(T,J),它们都是BCNF。

  • 3NF和BCNF是在函数依赖的条件下对模式分解所能达到的分离程度的测度。

  • 一个模式中的关系模式如果都属于BCNF,那么在函数依赖范畴内,它已实现了彻底的分离,已消除了插入和删除的异常。

  • 3NF的“不彻底”性表现在可能存在主属性对码的部分依赖和传递依赖。

6.2.7 多值依赖

:学校中某一门课程由多个教师讲授,他们使用相同的一套参考书。每个教员可以讲授多门课程,每种参考书可以供多门课程使用。用关系模式Teaching(C,T,B)来表示课程C、教师T和参考书B之间的关系。非规范化关系如下:

  • 规范化的二维表Teaching:

    • 课程 C | 教员 T | 参考书 B

    • 物理 | 李勇 | 普通物理学

    • 物理 | 李勇 | 光学原理

    • 物理 | 李勇 | 物理习题集

    • 物理 | 王军 | 普通物理学

    • 物理 | 王军 | 光学原理

    • 物理 | 王军 | 物理习题集

    • 数学 | 李勇 | 数学分析

    • 数学 | 李勇 | 微分方程

    • 数学 | 李勇 | 高等代数

    • 数学 | 张平 | 数学分析

    • 数学 | 张平 | 微分方程

    • 数学 | 张平 | 高等代数

    • … | … | …

  • Teaching具有唯一候选码(C,T,B),即全码。

  • Teaching∈BCNF

以上关系存在以下问题:

  1. 数据冗余度大:有多少名任课教师,参考书就要存储多少次。

  2. 增加操作复杂:当某一课程增加一名任课教师时,该课程有多少本参照书,就必须插入多少个元组。

  3. 删除操作复杂:某一门课要去掉一本参考书,该课程有多少名教师,就必须删除多少个元组。

  4. 修改操作复杂:某一门课要修改一本参考书,该课程有多少名教师,就必须修改多少个元组。

定义9:设R(U)是属性集U上的一个关系模式。X、Y、Z是U的子集,并且Z=U-X-Y。关系模式R(U)中多值依赖X→→Y成立,当且仅当对R(U)的任一关系r,给定的一对(x,z)值,有一组Y的值,这组值仅仅决定于x值而与z值无关。

:关系Teaching(C,T,B)中,对于C的每一个值,T有一组值与之对应,而不论B取何值。因此T多值依赖于C,即C→→T。

多值依赖的另一个等价的定义:在R(U)的任一关系r中,如果存在元组t,s使得t[X]=s[X],那么就必然存在元组w、v∈r(w、v可以与s、t相同),使得w[X]=v[X]=t[X],而w[Y]=t[Y],w[Z]=s[Z],v[Y]=s[Y],v[Z]=t[Z](即交换s,t元组的Y值所得的两个新元组必在r中,则Y多值依赖于X,记为X→→Y。这里X、Y是U的子集,Z=U-X-Y)。

平凡多值依赖:若X→→Y,而Z= ,即Z为空,则称X→→Y为平凡的多值依赖,否则称X→→Y为非平凡的多值依赖。

:关系模式WSC(W,S,C)中,W表示仓库,S表示保管员,C表示商品。假设每个仓库有若干个保管员,有若干种商品。每个保管员保管所在仓库的所有商品,每种商品被所有保管员保管。

  • 按照语义对于W的每一个值Wi,S有一个完整的集合与之对应而不问C取何值。所以W→→S。

  • W S C

    • W1 | S1 | C1

    • W1 | S1 | C2

    • W1 | S1 | C3

    • W1 | S2 | C1

    • W1 | S2 | C2

    • W1 | S2 | C3

    • W2 | S3 | C4

    • W2 | S3 | C5

    • W2 | S4 | C4

    • W2 | S4 | C5

  • 用下图表示WSC关系:

    • 对应W的某一个值Wi的全部S值记作{S}Wi(表示此仓库工作的全部保管员)。

    • 全部C值记作{C}Wi(表示在此仓库中存放的所有商品)。

    • 应当有{S}Wi中的每一个值和{C}Wi中的每一个C值对应。

    • 于是{S}Wi与{C}Wi之间正好形成一个完全二分图,故W→→S。

    • 由于C与S的完全对称性,必然有W→→C成立。

多值依赖的性质

  1. 多值依赖具有对称性:若X→→Y,则X→→Z,其中Z=U-X-Y。

  2. 多值依赖具有传递性:若X→→Y,Y→→Z,则X→→Z-Y。

  3. 函数依赖是多值依赖的特殊情况:若X→Y,则 X→→Y。

  4. 若X→→Y,X→→Z,则X→→YZ。

  5. 若X→→Y,X→→Z,则X→→Y∩Z。

  6. 若X→→Y,X→→Z,则X→→Y-Z,X→→Z-Y。

多值依赖与函数依赖的区别

  1. 多值依赖的有效性与属性集的范围有关。

    • 若X→→Y在U上成立,则在W(XY W U)上一定成立;反之则不然,即X→→Y在W(W U)上成立,在U上并不一定成立。

    • 原因:多值依赖的定义中不仅涉及属性组X和Y,而且涉及U中其余属性Z。

    • 一般地,在R(U)上若有X→→Y在W(W U)上成立,则称X→→Y为R(U)的嵌入型多值依赖。

    • 函数依赖X→Y的有效性仅决定于X、Y这两个属性集的值。只要在R(U)的任何一个关系r中,元组在X和Y上的值满足定义1,则函数依赖X→Y在任何属性集W(XY W U)上成立。

  2. 若函数依赖X→Y在R(U)上成立,则对于任何Y' Y均有X→Y'成立。多值依赖X→→Y若在R(U)上成立,不能断言对于任何Y' Y有X→→Y'成立。

:关系R(A,B,C,D),A→→BC成立,也有A→→D成立。有R的一个关系实例如下表,在此实例上A→→B是不成立的。

  • A | B | C | D

  • a1 | b1 | c1 | d1

  • a1 | b1 | c1 | d2

  • a1 | b2 | c2 | d1

  • a1 | b2 | c2 | d2

6.2.8 4NF

定义10:关系模式R<U,F>∈1NF,如果对于R的每个非平凡多值依赖X→→Y(X Y),X都含有码,则R<U,F>∈4NF。

说明

  1. 4NF是限制关系模式的属性之间不允许有非平凡且非函数依赖的多值依赖。4NF所允许的非平凡多值依赖实际是函数依赖。

  2. 如果一个关系模式是4NF,则必为BCNF。

  3. 在关系WSC中,W→→S,W→→C,他们都是非平凡多值依赖。而W不是码,关系模式WSC的码是(W,S,C),即All-key,因此WSC ∉ 4NF。可以把WSC分解成WS(W,S),WC(W,C),WS∈4NF,WC∈4NF。

6.2.9 规范化小结

  1. 在关系数据库中,对关系模式的基本要求是满足第一范式。

  2. 规范化程度过低的关系不一定能够很好地描述现实世界。可能存在插入异常、删除异常、修改复杂、数据冗余等问题,解决方法就是对其进行规范化,转换成高级范式。

  3. 一个低一级范式的关系模式,通过模式分解可以转换为若干个高一级范式的关系模式集合,这种过程就叫关系模式的规范化。

  4. 关系数据库的规范化理论是数据库逻辑设计的工具。

  5. 规范化的基本思想:

    • 逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”。

    • 采用“一事一地”的模式设计原则。让一个关系描述一个概念、一个实体或者实体间的一种联系。若多于一个概念就把它“分离”出去。因此规范化实质上是概念的单一化。

  6. 不能说规范化程度越高的关系模式就越好。必须对现实世界的实际情况和用户应用需求作进一步分析,确定一个合适的、能够反映现实世界的模式。

规范化的过程:通过逐步消除不合适的依赖,将关系模式分解为更高级的范式,以减少数据冗余、插入异常、删除异常和更新异常等问题。规范化的目标是使关系模式更加符合现实世界的逻辑结构,同时提高数据库操作的效率和一致性。

6.3 数据依赖的公理系统

定义11

对于满足一组函数依赖F的关系模式R<U,F>,其任何一个关系r,若函数依赖X→Y都成立(即r中任意两元组t、s,若t[X]=s[X],则t[Y]=s[Y]),则称F逻辑蕴涵X→Y。

Armstrong公理系统

是一套推理规则,是模式分解算法的理论基础。主要用于求给定关系模式的码,从一组函数依赖求得蕴涵的函数依赖。

Armstrong公理系统设U为属性集总体,F是U上的一组函数依赖,于是有关系模式R<U,F>,对R<U,F>来说有以下的推理规则:

  1. A1自反律(reflexivity rule):若Y X U,则X→Y为F所蕴涵。

  2. A2增广律(augmentation rule):若X→Y为F所蕴涵,且Z U,则XZ→YZ为F所蕴涵。

  3. A3传递律(transitivity rule):若X→Y及Y→Z为F所蕴涵,则X→Z为F所蕴涵。

注意:由自反律所得到的函数依赖均是平凡的函数依赖,自反律的使用并不依赖于F。

定理1:Armstrong推理规则是正确的。

证明

  1. 设Y X U。

    • 对R<U,F>的任一关系r中的任意两个元组t、s:若t[X]=s[X],由于Y X,有t[Y]=s[Y],所以X→Y成立,自反律得证。

  2. 设X→Y为F所蕴涵,且Z U。

    • 设R<U,F>的任一关系r中任意的两个元组t、s:若t[XZ]=s[XZ],则有t[X]=s[X]和t[Z]=s[Z];由X→Y,于是有t[Y]=s[Y],所以t[YZ]=s[YZ],XZ→YZ为F所蕴涵,增广律得证。

  3. 设X→Y,及Y→Z为F所蕴涵。

    • 对R<U,F>的任一关系r中的任意两个元组t、s:若t[X]=s[X],由于X→Y,有t[Y]=s[Y];再由Y→Z,有t[Z]=s[Z],所以X→Z为F所蕴涵,传递律得证。

根据A1,A2,A3这三条推理规则得到下面三条推理规则:

  1. 合并规则(union rule):由X→Y,X→Z,有X→YZ。

  2. 伪传递规则(pseudo transitivity rule):由X→Y,WY→Z,有XW→Z。

  3. 分解规则(decomposition rule):由X→Y及Z Y,有X→Z。

根据合并规则和分解规则,可得:

  • 引理1:X→A1A2…Ak成立的充分必要条件是X→Ai成立(i=1,2,…,k)。

定义12:在关系模式R<U,F>中为F所逻辑蕴涵的函数依赖的全体叫作F的闭包,记为F+。

说明

  1. 自反律、传递律和增广律称为Armstrong公理系统。

  2. Armstrong公理系统具有有效性和完备性。

    • 有效性是指由F出发根据Armstrong公理系统推导出的每一个函数依赖一定在F+中。

    • 完备性是指F+中的每一个函数依赖,必定可以由F出发根据Armstrong公理系统推导出来。

定义13:设F为属性集U上的一组函数依赖,X、Y U,X+ F={A|X→A能由F根据Armstrong公理导出},X+ F称为属性集X关于函数依赖集F的闭包。

引理2:设F为属性集U上的一组函数依赖,X、Y U,X→Y能由F根据Armstrong公理导出的充分必要条件是Y X+ F。

算法1:求属性集X(X U)关于U上的函数依赖集F的闭包X+ F。

  • 输入:X,F

  • 输出:X+ F

  • 步骤:

    1. 令X(0)=X,i=0。

    2. 求B,这里B={A|( V)( W)(V→W∈F∧V X(i)∧A∈W)}。

    3. X(i+1)=B∪X(i)。

    4. 判断X(i+1)=X(i)。

    5. 若X(i+1)与X(i)相等或X(i)=U,则X(i)就是X+ F,算法终止。

    6. 若否,则i=i+1,返回第2步。

例11:已知关系模式R<U,F>,其中U={A,B,C,D,E};F={AB→C,B→D,C→E,EC→B,AC→B},求(AB)+ F。

  • 解:由算法1,设X(0)=AB。

    • 计算X(1):逐一扫描F集合中各个函数依赖,找左部为A、B或AB的函数依赖。得到两个:AB→C,B→D。于是X(1)=AB∪CD=ABCD。

    • 因为X(0)≠X(1),所以再找出左部为ABCD子集的那些函数依赖,又得到C→E,AC→B,于是X(2)=X(1)∪BE=ABCDE。

    • 因为X(2)已等于全部属性集合,所以(AB)+ F=ABCDE。

定理2:Armstrong公理系统是有效的、完备的。

  • 证明:

    • 有效性:可由定理1得证。

    • 完备性:只需证明逆否命题:若函数依赖X→Y不能由F从Armstrong公理导出,那么它必然不为F所蕴含。

      • 引理:若V→W成立,且V X+ F,则W X+ F。

      • 构造一张二维表r,它由下列两个元组构成,可以证明r必是R(U,F)的一个关系,即F+中的全部函数依赖在r上成立。

        • X+ F | U-X+ F

        • 11......1 | 00......0

        • 11......1 | 11......1

      • 若X→Y不能由F从Armstrong公理导出,则Y不是X+ F的子集。因此必有Y的子集Y'满足Y' U-X+ F,则X→Y在r中不成立,即X→Y必不为R<U,F>蕴涵。

定义14:如果G+=F+,就说函数依赖集F覆盖G(F是G的覆盖,或G是F的覆盖),或F与G等价。

引理3:F+=G+的充分必要条件是F G+和G F+。

  • 证:必要性显然,只证充分性。

    • 若F G+,则X+ F X+ G。

    • 任取X→Y∈F+,则有Y X+ F X+ G。所以X→Y∈(G+)+=G+。即F+ G+。

    • 同理可证G+ F+,所以F+=G+。

定义15:如果函数依赖集F满足下列条件,则称F为一个极小函数依赖集。亦称为最小依赖集或最小覆盖。

  1. F中任一函数依赖的右部仅含有一个属性。

  2. F中不存在这样的函数依赖X→A,使得F与F-{X→A}等价。

  3. F中不存在这样的函数依赖X→A,X有真子集Z使得F-{X→A}∪{Z→A}与F等价。

:关系模式S<U,F>,其中:

  • U={Sno,Sdept,Mname,Cno,Grade},

  • F={Sno→Sdept,Sdept→Mname,(Sno,Cno)→Grade}。

  • 设F'={Sno→Sdept,Sno→Mname,Sdept→Mname,(Sno,Cno)→Grade,(Sno,Sdept)→Sdept}。

  • F是最小覆盖,而F'不是。因为:

    • F'-{Sno→Mname}与F'等价。

    • F'-{(Sno,Sdept)→Sdept}也与F'等价。

定理3:每一个函数依赖集F均等价于一个极小函数依赖集Fm。此Fm称为F的最小依赖集。

  • 证明:构造性证明,找出F的一个最小依赖集。

    • 逐一检查F中各函数依赖FDi:X→Y,若Y=A1A2…Ak,k≥2,则用{X→Aj|j=1,2,…,k}来取代X→Y。

    • 逐一检查F中各函数依赖FDi:X→A,令G=F-{X→A},若A∈X+ G,则从F中去掉此函数依赖。

    • 逐一取出F中各函数依赖FDi:X→A,设X=B1B2…Bm,m≥2,逐一考查Bi(i=1,2,…,m),若A∈(X-Bi)+ F,则以X-Bi取代X。

:F={A→B,B→A,B→C,A→C,C→A}

  • Fm1、Fm2都是F的最小依赖集:

    • Fm1={A→B,B→C,C→A}

    • Fm2={A→B,B→A,A→C,C→A}

  • F的最小依赖集Fm不唯一,极小化过程(定理3的证明)也是检验F是否为极小依赖集的一个算法。

6.4 模式的分解

定义16

关系模式R<U,F>的一个分解: ρ={R1<U1,F1>,R2<U2,F2>,…,Rn<Un,Fn>}

  • 其中,U=U1∪U2∪…∪Un,并且没有Ui Uj,1≤i,j≤n,Fi为F在Ui上的投影。

定义17

函数依赖集合{X→Y|X→Y∈F+∧XY Ui}的一个覆盖Fi叫作F在属性Ui上的投影。

6.4.1 模式分解的三个定义

对于一个模式的分解是多种多样的,但是分解后产生的模式应与原模式等价。对“等价”的概念形成了三种不同的定义:

  1. 分解具有无损连接性。

  2. 分解要保持函数依赖。

  3. 分解既要保持函数依赖,又要具有无损连接性。

说明:这三个定义实际是实行分解的三条不同的准则。按照不同的分解准则,模式所能达到的分离程度各不同,各种范式就是对分离程度的测度。

:已知关系R<U,F>,其中,U={Sno,Sdept,Mname},F={Sno→Sdept,Sdept→Mname}。

  • R<U,F>的元组语义是学生Sno正在Sdept系学习,系主任是Mname;并且一个学生(Sno)只在一个系学习,一个系只有一个系主任。R的一个关系见下表。

    • Sno | Sdept | Mname

    • S1 | D1 | 张五

    • S2 | D1 | 张五

    • S3 | D2 | 李四

    • S4 | D3 | 王一

  • 该模式存在的问题:更新异常,如果S4毕业了,则D3系的系主任王一的信息也就丢掉了。反过来,如果一个系D5尚无在校学生,那么这个系的系主任赵某的信息也无法存入。

  • 问题的原因:R中存在传递函数依赖Sno→Mname。

  • 解决方法:模式分解,下面进行三种模式分解,并分析那种分解更合理?

方法一:ρ1={R1<Sno, >,R2<Sdept, >,R3<Mname, >}

  • (注:R1<Sno, >表示R1的函数依赖集为 )

  • 分解后诸Ri的关系ri是R在Ui上的投影,即ri=R[Ui]。

    • r1={S1,S2,S3,S4},r2={D1,D2,D3},r3={张五,李四,王一}。

  • R1 R2 R3

  • 该分解的缺点:分解后的数据库丢失了许多信息;例如无法查询S1学生所在系以及系主任的信息。

  • 如果分解后的数据库能够恢复到原来的情况,不丢失信息的要求也就达到了。

方法二:ρ2={R1<{Sno,Sdept},{Sno→Sdept}>,R2<{Sno,Mname},{Sno→Mname}>}。

  • R1 R2

    • Sno | Sdept

    • S1 | D1

    • S2 | D1

    • S3 | D2

    • S4 | D3

    • Sno | Mname

    • S1 | 张五

    • S2 | 张五

    • S3 | 李四

    • S4 | 王一

  • 说明:ρ2对R的分解是可恢复的,但是前面提到的插入和删除异常仍然没有解决,原因就在于原来在R中存在的函数依赖Sdept→Mname,在R1和R2中都不再存在了。因此人们又要求分解具有“保持函数依赖”的特性。

方法三:ρ3={R1<{Sno, Sdept},{Sno→Sdept}>,R2<{Sdept, Mname},{Sdept→Mname}>}。

  • R1 R2

    • Sno | Sdept

    • S1 | D1

    • S2 | D1

    • S3 | D2

    • S4 | D3

    • Sdept | Mname

    • D1 | 张五

    • D2 | 李四

    • D3 | 王一

  • ρ3既具有无损连接性,又保持函数依赖。它解决了更新异常,又没有丢失原数据库的信息,这是所希望的分解。

6.4.2 分解的无损连接性和保持函数依赖性

定义以下记号

  • 设ρ={R1<U1,F1>,R2<U2,F2>,…,Rk<Uk,Fk>}是R的一个分解,r是R<U,F>的一个关系。定义mρ(r)= πRi(r),即mρ(r)是r在ρ中各关系模式上投影的连接。

  • πRi(r)={t.Ui|t∈r},即r中的每一个元组t在属性Ui上的取值。

  • i=1

  • k

  • 说明

    • 注意mρ(r)的含义不同于一般的自然连接,它是一种特殊的连接运算。上式含义为:

      • 如果两个关系中有相同的属性列,则按第二章中的自然连接的定义进行;

      • 如果两个关系中没有相同的属性列,则按笛卡儿积运算进行;

      • 将运算后得到的结果与其他关系进行重复1、2步的计算,直到完成全部的连接运算。

引理4:设ρ={R1<U1,F1>,R2<U2,F2>, … ,Rk<Uk,Fk>}为关系模式R的一个分解,r为R的任一个关系,ri=πRi(r),则

  1. r mρ(r)(即r的投影连接包含r)

  2. 如果s=mρ(r),则πRi(s)=ri

  3. mρ(mρ(r))=mρ(r)

说明

  1. r mρ(r):r的投影连接包含,分解后再连接起来的r肯定不会比原来的r小。

  2. 如果s=mρ(r),则πRi(s)=ri:投影连接后再投影到子关系模式=直接投影到该子关系模式。即πRi(r)=πRi(mρ(r))。

  3. mρ(mρ(r))=mρ(r):多次投影连接的结果等于一次投影连接后的结果。

:设有关系模式R(A,B,C),ρ={R1,R2}为它的一个分解,其中R1=AB,R2=BC,r为R的一个关系,r1=πR1(r),r2=πR2(r)。

  • 求r1,r2,mρ(r),由此可得到什么结论?

    • r

      • A | B | C

      • a1 | b1 | c1

      • a2 | b1 | c2

      • a1 | b1 | c2

    • r1=πR1(r)

      • A | B

      • a1 | b1

      • a2 | b1

    • r2=πR2(r)

      • B | C

      • b1 | c1

      • b1 | c2

    • mρ(r)

      • A | B | C

      • a1 | b1 | c1

      • a1 | b1 | c2

      • a2 | b1 | c1

      • a2 | b1 | c2

    • r1=πR1(mρ(r))

      • A | B

      • a1 | b1

      • a2 | b1

    • r2=πR2(mρ(r))

      • B | C

      • b1 | c1

      • b1 | c2

  • 结论:分解后的关系进行自然联接必包含分解前的关系,即分解不会丢失信息,但可能增加信息,只有r=mρ(r)时,分解才具有无损联接性。

定义18:关系模式R<U,F>的一个分解: ρ={R1<U1,F1>,R2<U2,F2>,…,Rk<Uk,Fk>}

  • 若对于R的任何一个关系r均有r=mρ(r)成立,则称分解ρ具有无损连接性。简称ρ为无损连接。

算法2:判别一个分解的无损连接性。

  • ρ={R1<U1,F1>,R2<U2,F2>,…,Rk<Uk,Fk>}是R<U,F>的一个分解,U={A1,A2,…,AN},F={FD1,FD2,…,FDρ},设F是一极小依赖集,记FDi为Xi→Ali。

    1. 构造初始表:构造一个k行n列的初始表,其中每列对应于R的一个属性,每行用于表示分解后的一个模式组成。如果属性Aj属于关系模式Ri,则在表的第i行第j列置符号aj否则置符号bij。

    2. 根据F中的函数依赖修改表内容

      • 对每个FDi做下列操作:找到Xi具有相同符号的行,考察这些行中li列的元素。若其中有ali,则全部改为ali;否则全部改为bmli。其中m是这些行的行号最小值。

      • 注意:若某个btli被更改,则表的li列中凡是btli的符号(不管它是否开始找到的那些行)均应做相应的更改。

    3. 循环执行以上操作,若有一行变为a1,a2,…,an,则算法终止,ρ具有无损连接性,否则ρ不具有无损连接性。

    4. 比较扫描前后表有无变化,如有变化则返回2中,否则算法终止。

定理4:如果算法2终止时表中有一行为a1,a2,…,an,则ρ为无损连接分解。

:已知R<U,F>,U={A,B,C,D,E},F={AB→C,C→D,D→E},R的一个分解为R1(A,B,C),R2(C,D),R3(D,E)。

  1. 第一步:构建初始表如下:

    • A | B | C | D | E

    • a1 | a2 | a3 | b14 | b15

    • b21 | b22 | a3 | a4 | b25

    • b31 | b32 | b33 | a4 | a5

  2. 第二步:

    • 对AB→C,因各元组的第一、二列没有相同分量,所以表不变。

    • C→D可以把b14改为a4。

    • D→E可以把b15、b25改为a5,如下表,表中第一行为a1,a2,a3,a4,a5,所以此分解具有无损连接性。

      • A | B | C | D | E

      • a1 | a2 | a3 | a4 | a5

      • b21 | b22 | a3 | a4 | a5

      • b31 | b32 | b33 | a4 | a5

当关系模式R分解为两个关系模式R1、R2时有下面的判定准则

  • 定理5:对于R<U,F>的一个分解ρ={R1<U1,F1>,R2<U2,F2>},如果(U1∩U2)→U1-U2∈F+ 或(U1∩U2)→U2-U1∈F+,则ρ具有无损连接性。

定义19:若F+=∪Fi+,则R<U,F>的分解ρ={R1<U1,F1>,…,Rk<Uk,Fk>}保持函数依赖。

6.4.3 模式分解的算法

关于模式分解的几个重要事实

  1. 若要求分解保持函数依赖,那么模式分解总可以达到3NF,但不一定能达到BCNF。

  2. 若要求分解既保持函数依赖,又具有无损连接性,可以达到3NF,但不一定能达到BCNF。

  3. 若要求分解具有无损连接性,那一定可达到4NF。

算法3(合成法):转换为3NF的保持函数依赖的分解。

  1. 对R<U,F>中的F进行极小化处理。

  2. 找出不在F中出现的属性(记作U0),把这样的属性构成一个关系模式R0<U0,F0>,把这些属性从U中去掉,剩余的属性仍记为U。

  3. 若有X→A∈F,且XA=U,则ρ={R},算法终止。

  4. 否则,对F按具有相同左部的原则分组(假定分为K组),每一组函数依赖所涉及的全部属性形成一个属性集Ui。若Ui Uj (i≠j)就去掉Ui,于是ρ={R1<U1,F1>,…,Rk<Uk,Fk>}∪R0<U0,F0>构成R<U,F>的一个保持函数依赖的分解,并且每个Ri<Ui,Fi>均属于3NF。

:R(Sno,Sname,Sdept,Mname),F={Sno→Sname,Sno→Sdept,Sdept→Mname},分解R,使其保持函数依赖达到3NF。

  • 解:F已经是最小集,同时也找不出不在F中出现的属性,现将F按照相同左部原则进行分组,结果为:

    • R1<(Sno,Sname,Sdept),Sno→Sname,Sno→Sdept}>

    • R2<(Sdept,Mname),Sdept→Mname>

算法4:转换为3NF既有无损连接性又保持函数依赖的分解。

  1. 设X是R〈U,F〉的码,R〈U,F〉已有算法3分解为ρ={R1<U1,F1>,…,Rk<Uk,Fk>}∪R0<U0,F0> ,令τ=ρ∪{R*<X,FX>}。

  2. 如有某个Ui,X Ui,将R*<X,FX>从τ中去掉,或者Ui X,将R<Ui,FX>从τ中去掉。

  3. τ就是所求的分解。

:设R(ABCDE),F={A→B,C→D},分解R为一组3NF的关系模式,要求分解既具有无损联接性又保持函数依赖。

  • 解:

    • ACE为侯选码;

    • 按算法3,ρ={R1(AB),R2(CD)};

    • 判断侯选码ACE不在分解后的子关系模式中,所以加上码ACE组成的模式R3(ACE)。

    • 所以ρ={R1(AB),R2(CD),R3(ACE)}是一个3NF的关系模式,既具有无损联接性又保持函数依赖。

算法5(分解法):转换为BCNF的无损连接分解。

  1. 令ρ={R<U,F>}。

  2. 检查ρ中各关系模式是否均属于BCNF。若是,则算法终止。

  3. 设ρ中Ri<Ui,Fi>不属于BCNF,那么必有X→A∈Fi+(A∉X),且X非Ri的码。因此,XA是Ui的真子集。对Ri进行分解:σ={S1,S2},US1=XA,US2=Ui-{A},以σ代替Ri(Ui,Fi)返同第(2)步。

引理5:若ρ={R1<U1,F1>,…,Rk<Uk,Fk>}是R<U,F>的一个无损连接分解,σ={S1,S2,…,Sm}是ρ中Ri<Ui,Fi>的一个无损连接分解,那么,ρ′={R1,R2,…,Ri-1,S1,S2,…,Sm,Ri+1,…,Rk}和ρ″={R1,…,Rk,Rk+1,…,Rn},均为R<U,F>的无损连接分解。

引理6:(R1 R2) R3=R1 (R2 R3)

定理6:关系模式R<U,D>中,D为R中函数依赖FD和多值依赖MVD的集合。则X→→Y成立的充分必要条件是:

  • R的分解ρ={R1<X,Y>,R2<X,Z>}具有无损连接性,其中Z=U-X-Y。

算法6:达到4NF的具有无损连接性的分解。

  1. 首先使用算法5得到R的一个达到BCNF的无损连接分解ρ,然后

  2. 对某一个Ri<Ui,Fi>,若不属于4NF,则可按定理6进行分解,直到每一个关系模式均属于4NF为止。

包含函数依赖和多值依赖的有效且完备的公理系统

  1. A1:若Y X U,则X→Y。

  2. A2:若X→Y,且Z U,则XZ→YZ。

  3. A3:若X→Y,Y→Z,则X→Z。

  4. A4:若X→→Y,V W U,则XW→YV。

  5. A5:若X→→Y,则X→→U-X-Y。

  6. A6:若X→→Y,Y→→Z,则X→→Z-Y。

  7. A7:若X→Y,则X→→Y。

  8. A8:若X→→Y,W→Z,W∩Y=φ,Z Y,则X→Z。

由以上8条公理得知如下4条有用的推理规则:

  1. 合并规则:X→→Y,Y→→Z,则X→→YZ。

  2. 伪传递规则:X→→Y,WY→→Z,则WX→→Z-WY。

  3. 混合伪传递规则:X→→Y,XY→→Z,则X→→Z-Y。

  4. 分解规则:X→→Y,X→Z,则X→→Y∩Z,X→→Y-Z,X→→Z-Y。

6.5 小结

  1. 关系模式的规范化,其基本思想如下:

    • 逐步消除数据依赖中不合适的部分,使模式中的各关系模式达到某种程度的“分离”。

    • 采用“一事一地”的模式设计原则。让一个关系描述一个概念、一个实体或者实体间的一种联系。若多于一个概念就把它“分离”出去。因此规范化实质上是概念的单一化。

  2. 规范化理论为数据库设计提供理论的指南和工具,仅仅是指南和工具。

  3. 并不是规范化程度越高,模式就越好,必须结合应用环境和现实世界的具体情况合理地选择数据库模式。

第7章 数据库设计

7.1 数据库设计概述

  1. 数据库设计定义:对于一个给定的应用环境,构造优化的数据库逻辑模式和物理结构,并据此建立数据库及其应用系统,使之能够有效地存储和管理数据,满足各种用户的应用需求,包括信息管理要求和数据操作要求。

  2. 信息管理要求:在数据库中应该存储和管理哪些数据对象。

  3. 数据操作要求:对数据对象需要进行哪些操作,如查询、增、删、改、统计等操作。

  4. 数据库设计的目标:为用户和各种应用系统提供一个信息基础设施和高效率的运行环境。

  5. 高效率的运行环境

    • 数据库数据的存取效率高;

    • 数据库存储空间的利用率高;

    • 数据库系统运行管理的效率高。

  6. 数据库设计的特点

    • 数据库建设的基本规律:三分技术,七分管理,十二分基础数据。管理包括数据库建设项目管理和企业(应用部门)的业务管理,基础数据包括数据的收集、整理、组织和不断更新。

    • 结构(数据)设计和行为(处理)设计相结合:将数据库结构设计和数据处理设计密切结合。传统的软件工程重行为设计,忽视对应用中数据语义的分析和抽象,尽量推迟数据结构设计的决策;早期的数据库设计重结构设计,致力于数据模型和数据库建模方法研究,忽视了行为设计对结构设计的影响。

  7. 数据库设计方法

    • 手工与经验结合的方法

      • 存在问题:

        • 设计质量与设计人员的经验和水平有直接关系。

        • 缺乏科学理论和工程方法的支持,工程的质量难以保证。

        • 数据库运行一段时间后常常又不同程度地发现各种问题,增加了维护代价。

    • 规范设计法

      • 基本思想:过程迭代和逐步求精。

      • 典型方法:新奥尔良(New Orleans)方法、基于E-R模型的数据库设计方法、3NF(第三范式)的设计方法、面向对象的数据库设计方法、统一建模语言(UML)方法。

  8. 数据库设计的基本步骤

    • 数据库设计分6个阶段

      • 需求分析、概念结构设计、逻辑结构设计、物理结构设计、数据库实施、数据库运行和维护。

      • 说明

        • 需求分析和概念设计独立于任何数据库管理系统。

        • 逻辑设计和物理设计与选用的数据库管理系统密切相关。

    • 参加数据库设计的人员

      • 系统分析人员和数据库设计人员:自始至终参与数据库设计,其水平决定了数据库系统的质量。

      • 数据库管理员和用户代表:要参加需求分析与数据库的运行和维护。

      • 应用开发人员:包括程序员和操作员,在实施阶段参与进来,分别负责编制程序和准备软硬件环境。

    • 各阶段的主要任务

      • 需求分析阶段:了解用户需求,该阶段是否做得充分与准确,决定了构建数据库的速度和质量。

      • 概念结构设计阶段:对用户需求进行综合、归纳与抽象,形成一个独立于具体数据库管理系统的概念模型。

      • 逻辑结构设计阶段:将概念结构转换为数据库管理系统所支持的数据模型,并对其进行优化。

      • 物理结构设计阶段:逻辑数据结构选取一个最适合应用环境的物理结构,包括存储结构和存取方法。

      • 数据库实施阶段:根据逻辑设计和物理设计的结果构建数据库,编写与调试应用程序,组织数据入库并进行试运行。

      • 数据库运行和维护阶段:经过试运行后即可投入正式运行,在运行过程中必须不断对其进行评估、调整与修改。

      • 说明

        • 设计一个完善的数据库应用系统往往是上述6个阶段的不断反复。

        • 设计步骤既是数据库设计的过程,也包括了数据库应用系统的设计过程。

        • 把数据库的设计和数据处理的设计紧密结合,将这两个方面的需求分析、抽象、设计、实现在各个阶段同时进行。

    • 各个阶段的数据设计描述

      • 需求分析阶段:综合各个用户的应用需求。

      • 概念设计阶段:形成独立于机器特点,独立于各个数据库管理系统产品的概念模式(E-R图)。

      • 逻辑设计阶段:

        • 首先将E-R图转换成具体的数据库产品支持的数据模型,如关系模型,形成数据库逻辑模式。

        • 然后根据用户处理的要求、安全性的考虑,在基本表的基础上再建立必要的视图(View),形成数据的外模式。

      • 物理设计阶段:根据数据库管理系统特点和处理的需要,进行物理存储安排,建立索引,形成数据库内模式。

  9. 数据库设计过程中的各级模式:(内容未提及具体内容)

7.2 需求分析

  1. 需求分析的任务

    • 详细调查现实世界要处理的对象(组织、部门、企业等)。

    • 充分了解原系统(手工系统或计算机系统)工作概况。

    • 明确用户的各种需求。

    • 确定新系统的功能,新系统必须充分考虑今后可能的扩充和改变。

    • 说明:调查的重点是“数据”和“处理”,获得用户对数据库在信息、处理、安全性与完整性的要求。

  2. 需求分析的方法

    • 需求分析的目的:调查清楚用户的实际需求并进行初步分析,最终与用户达成共识。

    • 调查用户需求的步骤

      • 调查组织机构情况。

      • 调查各部门的业务活动情况。

      • 协助用户明确对新系统的各种要求,包括信息要求、处理要求、完全性与完整性要求。

      • 确定新系统的边界。

    • 常用的调查方法

      • 跟班作业:通过亲身参加业务工作了解业务活动的情况。

      • 开调查会:通过与用户座谈来了解业务活动情况及用户需求。

      • 请专人介绍。

      • 询问:对某些调查中的问题,可以找专人询问。

      • 设计调查表请用户填写:调查表设计合理,则很有效。

      • 查阅记录:查阅与原系统有关的数据记录。

    • 结构化分析方法(Structured Analysis,简称SA方法):SA方法从最上层的系统组织机构入手,采用自顶向下、逐层分解的方式分析系统。

  3. 数据字典

    • 定义:数据字典是关于数据库中数据的描述,即元数据,不是数据本身。数据字典是在需求分析阶段建立,是进行详细的数据收集和数据分析所获得的,并在数据库设计过程中不断修改、充实、完善。

    • 内容

      • 数据项:数据项是不可再分的数据单位。

        • 数据项描述={数据项名,数据项含义说明,别名,数据类型,长度,取值范围,取值含义,与其他数据项的逻辑关系,数据项之间的联系}

        • 说明

          • “取值范围”、“与其他数据项的逻辑关系”定义了数据的完整性约束条件,是设计数据检验功能的依据。

          • 可以用关系规范化理论为指导,用数据依赖的概念分析和表示数据项之间的联系。

      • 数据结构:数据结构反映了数据之间的组合关系。

        • 数据结构描述={数据结构名,含义说明,组成:{数据项或数据结构}}

        • 说明:一个数据结构可以由若干个数据项组成,也可以由若干个数据结构组成,或由若干个数据项和数据结构混合组成。

      • 数据流:是数据结构在系统内传输的路径。

        • 数据流描述={数据流名,说明,数据流来源,数据流去向,组成:{数据结构},平均流量,高峰期流量}

        • 说明

          • 数据流来源:说明该数据流来自哪个过程。

          • 数据流去向:说明该数据流将到哪个过程去。

          • 平均流量:在单位时间(每天、每周、每月等)里的传输次数。

          • 高峰期流量:在高峰时期的数据流量。

      • 数据存储:数据结构停留或保存的地方,也是数据流的来源和去向之一。

        • 数据存储描述={数据存储名,说明,编号,输入的数据流,输出的数据流,组成:{数据结构},数据量,存取频度,存取方式}

        • 说明

          • 存取频度:每小时、每天或每周存取次数,每次存取的数据量等信息。

          • 存取方法:批处理/联机处理;检索/更新;顺序检索/随机检索。

          • 输入的数据流:数据来源。

          • 输出的数据流:数据去向。

      • 处理过程:处理过程的具体处理逻辑一般用判定表或判定树来描述。数据字典中只需要描述处理过程的说明性信息。

        • 处理过程描述={处理过程名,说明,输入:{数据流},输出:{数据流},处理:{简要说明}}

        • 说明:“简要说明”说明该处理过程的功能及处理要求。其中功能是指该处理过程用来做什么。处理要求是指处理频度要求,如单位时间里处理多少事务,多少数据量、响应时间要求等。

  4. 需求分析小结

    • 需求收集和分析作为数据库设计的第一阶段是十分重要的。

    • 第一阶段收集的基础数据(用数据字典来表达)是下一步进行概念设计的基础。

    • 强调两点

      • 设计人员应充分考虑到可能的扩充和改变,使设计易于更改,系统易于扩充。

      • 必须强调用户的参与。

7.3 概念结构设计

  1. 概念模型

    • 定义:概念结构设计是将需求分析得到的用户需求抽象为信息结构(即概念模型)的过程。

    • 特点

      • 能真实、充分地反映现实世界,是现实世界的一个真实模型。

      • 易于理解,可以用它和不熟悉计算机的用户交换意见。

      • 易于更改,当应用环境和应用要求改变时,容易对概念模型修改和扩充。

      • 易于向关系、网状、层次等各种数据模型转换。

    • 描述工具:E-R模型。

  2. E-R模型

    • 实体之间的联系

      • 两个实体型之间的联系

        • 一对一联系(1∶1):如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之联系,反之亦然,则称实体集A与实体集B具有一对一联系,记为1∶1。

          • :学校里一个班级只有一个正班长,而一个班长只在一个班中任职,则班级与班长之间具有一对一联系。

        • 一对多联系(1∶n):如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系,反之,对于实体集B中的每一个实体,实体集A中至多只有一个实体与之联系,则称实体集A与实体集B有一对多联系,记为1∶n。

          • :一个班级中有若干名学生,而每个学生只在一个班级中学习,则班级与学生之间具有一对多联系。

        • 多对多联系(m∶n):如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系,反之,对于实体集B中的每一个实体,实体集A中也有m个实体(m≥0)与之联系,则称实体集A与实体集B具有多对多联系,记为m∶n。

          • :一门课程同时有若干个学生选修,而一个学生可以同时选修多门课程,则课程与学生之间具有多对多联系。

      • 两个以上的实体型之间的联系:一般地,两个以上的实体型之间也存在着一对一、一对多、多对多联系。

        • :对于课程、教师与参考书3个实体型,如果一门课程可以有若干个教师讲授,使用若干本参考书,而每一个教师只讲授一门课程,每一本参考书只供一门课程使用,则课程与教师、参考书之间的联系是一对多的。

      • 单个实体型内的联系:同一个实体集内的各实体之间也可以存在一对一、一对多、多对多的联系。

        • :职工实体型内部具有领导与被领导的联系,即某一职工(干部)“领导”若干名职工,而一个职工仅被另外一个职工直接领导,因此这是一对多的联系。

    • 联系的度:参与联系的实体型的数目。2个实体型之间的联系度为2,也称为二元联系;3个实体型之间的联系度为3,称为三元联系;N个实体型之间的联系度为N,也称为N元联系。

  3. E-R图

    • 定义:E-R图提供了表示实体型、属性和联系的方法。

    • 表示方法

      • 实体型:用矩形表示,矩形框内写明实体名。

      • 属性:用椭圆形表示,并用无向边将其与相应的实体型连接起来。

        • :学生实体具有学号、姓名、性别、出生年份、系、入学时间等属性,用E-R图如下。(图未给出)

      • 联系:用菱形表示,菱形框内写明联系名,并用无向边分别与有关实体型连接起来,同时在无向边旁标上联系的类型(1∶1,1∶n或m∶n)。联系也可以具有属性。

        • :如果用“供应量”来描述联系“联系”属性,表示某供应商供应了多少数量的零件给某项目,这三个实体及实体间联系的E-R图如下。(图未给出)

  4. 一个实例

    • 涉及的实体及属性

      • 仓库:属性有仓库号、面积、电话号码;

      • 零件:属性有零件号、名称、规格、单价、描述;

      • 供应商:属性有供应商号、姓名、地址、电话号码、账号;

      • 项目:属性有项目号、预算、开工日期;

      • 职工:属性有职工号、姓名、年龄、职称。

    • 实体之间的联系

      • 仓库和零件具有多对多的联系。一个仓库可以存放多种零件,一种零件可以存放在多个仓库中,用库存量来表示某种零件在某个仓库中的数量。

      • 仓库和职工之间是一对多的联系。一个仓库有多个职工当仓库保管员,一个职工只能在一个仓库工作。

      • 职工之间有领导与被领导关系。即仓库主任领导若干保管员,因此职工实体型中具有一对多的联系。

      • 供应商、项目和零件三者之间具有多对多的联系。即一个供应商可以供给若干项目多种零件,每个项目可以使用不同供应商供应的零件,每种零件可由不同供应商供给。

  5. 扩展的E-R模型

    • ISA联系

      • 定义:用E-R方法构建一个项目的模型时,经常会遇到某些实体型是某个实体型的子集,例如,研究所和本科生是学生的子类,学生是父类。这种父类-子类的联系称为ISA联系,表示“is a”的语义。

      • 表示方法:ISA联系用三角形来表示。

      • 说明:ISA联系描述了一个实体型中实体的一种分类方法,其一个重要性质是子类继承了父类的所有属性,同时子类也可有自己的属性。

      • 分类属性:根据分类属性的值把父实体型中的实体分派到子实体中。

        • :下图中在ISA联系符号三角形的右边加一个分类属性“学生类别”,说明一个学生是研究生还是本科生由“学生类别”这个属性决定。(图未给出)

      • 不相交约束与可重叠约束

        • 不相交约束:父类中的一个实体不能同时属于多个子类中的实体集,即一个父类中的实体最多属于一个子类实体集。用ISA联系三角形符号内加一个“X”来表示。

        • 可重叠约束:父类中的一个实体能同时属于多个子类中的实体集,三角形符号内没有“X”来表示。

      • 完备性约束:描述父类中一个实体是否必须是某一个子类中的实体。如果是,则为完全特化,否则为部分特化。完全特化用双线连接,部分特化用单线连接。

    • 基数约束:是对实体之间一对一、一对多和多对多联系的细化。约束用一数对min..max表示,0≤min≤max。

      • :0..1、1..3、1..代表无穷大)。

      • 强制参与约束与非强制参与约束

        • 强制参与约束:min=1的约束叫做强制参与约束,即被施加基数约束的实体型中的每个实体都要参与联系。

        • 非强制参与约束:min=0的约束叫做非强制参与约束,即被施加基数约束的实体可以出现在联系中,也可以不出现在联系中。

          • 学生和学生证联系中,一个学生必须拥有一本学生证,一本学生证只能属于一个学生,因此都是1..1。

          • 学生和课程联系中,假设学生实体型的基数约束是20..30,课程的一个合理的基数约束是0..*。

          • 班级和学生联系中,一个学生必须参加一个班,并只能参加一个班,因此为1..1,一个班级最少30个学生,最多40个学生,因此是30..40。

    • Part-of联系:即部分联系,表明某个实体型是另外一个实体型的一部分。

      • :汽车和轮子两个实体型,轮子是汽车的一部分,即Part-of汽车实体。

      • 分类

        • 非独占的Part-of联系:整体实体如果被破坏,部分实体仍然可以独立存在。非独占的Part-of联系可以通过基数约束来表达。

          • :汽车实体型和轮子实体型之间,汽车车体被毁坏了,轮子还存在,可以拆下来独立使用。(图未给出)

        • 独占的Part-of联系:实体如果被破坏,部分实体不能存在。在E-R图中用弱实体类型和识别联系来表示独占联系。

          • 弱实体型与强实体型

            • 如果一个实体型的存在依赖于其他实体型的存在,则这个实体型叫做弱实体型,否则叫做强实体型。

            • 判断方法:如果不能从一个实体型属性中找出可以作为码的属性,这个实体型是弱实体型。

          • 表示方法:在E-R图中用双矩形表示弱实体型,用双菱形表示识别联系。

            • 用户从银行贷款购房,这笔贷款一次贷出,分期归还。还款就是一个弱实体,因为它只有还款序号、日期和金额三个属性,第1笔还款的序号为1,第2笔还款的序号为2,以此类推,这些属性的组合都不能作为还款的码。还款的存在必须依赖于贷款实体。

            • 房间和楼房的联系。每座楼都有唯一的编号或名称,每个房间都有编号,如果房间号不包含楼号,则房间号不能作为码,所以房间是个弱实体。

  6. UML

    • 定义:UML是统一建模语言或标准建模语言,是始于1997年一个OMG标准,它是一个支持模型化和软件系统开发的图形化语言,为软件开发的所有阶段提供模型化和可视化支持,包括由需求分析到规格,到构造和配置。也可以作为表示E-R图的一种方法。

    • 表示E-R图的方法

      • 实体型:用类表示,矩形框上部写实体名,下面列出属性名。

      • 实体的码:在类图中属性后面加“PK”。

      • 联系:用类图之间的“关联”来表示。

      • :学生、课程它们之间的联系以及基数约束的E-R图用UML表示。(图未给出)

  7. 概念结构设计

    • 第一步:对需求分析阶段收集到的数据进行分类、组织,确定实体、实体属性、实体间联系类型,形成E-R图。

    • 实体与属性的划分原则

      • 为了简化E-R图的处置,现实世界的事物能作为属性对待的,尽量作为属性对待。

      • 两条准则

        • 作为属性,不能再具有需要描述的性质。属性必须是不可分的数据项,不能包含其他属性。

        • 属性不能与其他实体具有联系,即E-R图中所表示的联系是实体之间的联系。

        • 职工是一个实体,职工号、姓名、年龄是职工的属性。职称如果没有与工资、福利挂钩,根据准则(1)可以作为职工实体的属性。如果不同的职称有不同的工资、住房标准和不同的附加福利,则职称作为一个实体更恰当。

        • 在医院中,一个病人只能住在一个病房,病房号可以作为病人实体的一个属性;如果病房还要与医生实体发生联系,即一个医生负责几个病房的病人的医疗工作,则根据准则(2)病房应作为一个实体。

        • 如果一种货物只存放在一个仓库,那么就可以把存放货物的仓库的仓库号作为描述货物存放地点的属性。如果一种货物可以存放在多个仓库中,或者仓库本身又用面积作为属性,或者仓库与职工发生管理上的联系,那么就应把仓库作为一个实体。

      • :销售管理子系统E-R图的设计。

        • 该子系统的主要功能是:处理顾客和销售员送来的订单;工厂是根据订货安排生产的;交出货物同时开出发票;收到顾客付款后,根据发票存根和信贷情况进行应收款处理。

        • 先设计E-R草图如下:(图未给出)

        • 参照需求分析和数据字典中的详尽描述,遵循前面给出的两个准则,进行如下调整:

          • 订单与订单细节两个实体之间是1∶n的联系。每张订单由订单号、若干头信息和订单细节组成。订单细节又有订货的零件号、数量等来描述。按照准则(2),订单细节就不能作订单的属性处理而应该上升为实体。一张订单可以订若干产品。

          • 原订单和产品的联系实际上是订单细节和产品的联系。每条订货细节对应一个产品描述,订单处理时从中获得当前单价、产品重量等信息。

          • 增加一个“折扣规则”实体。工厂对大宗订货给予优惠。每种产品都规定了不同订货数量的折扣,应增加一个“折扣规则”实体存放这些信息,而不应把它们放在产品实体中。

        • 最后得到销售管理子系统E-R图如下:(图未给出)

        • 对每个实体定义的属性如下:

          • 顾客:{顾客号,顾客名,地址,电话,信贷状况,账目余额}

          • 订单:{订单号,顾客号,订货项数,订货日期,交货日期,工种号,生产地点}

          • 订单细则:{订单号,细则号,零件号,订货数,金额}

          • 应收账款:{顾客号,订单号,发票号,应收金额,支付日期,支付金额,当前余额,货款限额}

          • 产品:{产品号,产品名,单价,重量}

          • 折扣规则:{产品号,订货量,折扣}

    • E-R图的集成

      • 第一步:合并。解决各分E-R图之间的冲突,将分E-R图合并起来生成初步E-R图。

      • 第二步:修改和重构。消除不必要的冗余,生成基本E-R图。

      • 合并E-R图,生成初步E-R图

        • 各个局部应用所面向的问题不同,各个子系统的E-R图之间必定会存在许多不一致的地方,称之为冲突。

        • 子系统E-R图之间的冲突主要有三类:

          • 属性冲突

            • 属性域冲突,即属性值的类型、取值范围或取值集合不同。

              • :零件号,有的部门把它定义为整数,有的部门把它定义为字符型。年龄,某些部门以出生日期形式表示职工的年龄,而另一些部门用整数表示职工的年龄。零件的重量有的以公斤为单位,有的以斤为单位,有的以克为单位。

          • 命名冲突

            • 同名异义,即不同意义的对象在不同的局部应用中具有相同的名字。

            • 异名同义(一义多名),即同一意义的对象在不同的局部应用中具有不同的名字。

              • :对科研项目,财务科称为项目,科研处称为课题,生产管理处称为工程。

            • 命名冲突,可能发生在实体、联系一级上;也可能发生在属性一级上;通过讨论、协商等行政手段加以解决。

          • 结构冲突

            • 同一对象在不同应用中具有不同的抽象。

              • :职工在某一局部应用中被当作实体,而在另一局部应用中则被当作属性。

            • 解决方法:把属性变换为实体或把实体变换为属性,使同一对象具有相同的抽象。

            • 同一实体在不同子系统的E-R图中所包含的属性个数和属性排列次序不完全相同。

              • 解决方法:该实体的属性取各子系统的E-R图中属性的并集,再适当调整属性的次序。

            • 实体间的联系在不同的E-R图中为不同的类型。

              • :实体E1与E2在一个E-R图中是多对多联系,在另一个E-R图中是一对多联系。

            • 解决方法:是根据应用的语义对实体联系的类型进行综合或调整。

              • :零件与产品之间存在多对多的联系“构成”。产品、零件与供应商三者之间还存在多对多的联系“供应”。

              • 合并后:(图未给出)

      • 消除不必要的冗余,设计基本E-R图

        • 所谓冗余的数据是指可由基本数据导出的数据,冗余的联系是指可由其他联系导出的联系。

        • 消除冗余主要采用分析方法,即以数据字典和数据流图为依据,根据数据字典中关于数据项之间逻辑关系的说明来消除冗余。

        • 消除冗余后的初步E-R图,称为基本E-R图。

        • 说明:并不是所有的冗余数据与冗余联系都必须加以消除,有时为了提高效率,不得不以冗余信息作为代价。如果每次查询都要查询每个仓库中此种材料的库存,再求和,就使得查询效率低下。因此应保留Q4,同时把Q4=∑Q5定义为Q4的完整性约束条件。每当Q5修改后,触发完整性检查。

        • 用规范化理论来消除冗余:

          • 确定分E-R图实体之间的数据依赖:实体之间一对一、一对多、多对多的联系可以用实体码之间的函数依赖来表示。

            • :如下图:(图未给出)

              • 部门和职工之间一对多的联系可表示为:职工号→部门号。

              • 职工和产品之间多对多的联系可表示为:(职工号,产品号)→工作天数等。

            • 于是有函数依赖集FL。

          • 求FL的最小覆盖GL,差集为 D=FL-GL。逐一考察D中的函数依赖,确定是否是冗余的联系,若是,就把它去掉。

          • 注意两个问题

            • 冗余的联系一定在D中,而D中的联系不一定是冗余的。

            • 当实体之间存在多种联系时,要将实体之间的联系在形式上加以区分。

          • :某工厂管理信息系统的视图集成。

            • 工厂物资管理E-R图:(图未给出)

            • 销售管理子系统的E-R图:(图未给出)

            • 劳动人事管理的分E-R图:(图未给出)

            • 集成过程中需要解决以下问题:

              • 异名同义,项目和产品含义相同。某个项目实质上是指某个产品的生产。统一用产品作实体名。

              • 取消冗余联系,库存管理中职工与仓库的工作关系已包含在劳动人事管理的部门与职工之间的联系之中,所以可以取消。职工之间领导与被领导关系可由部门与职工(经理)之间的领导关系、部门与职工之间的从属关系两者导出,所以也可以取消。

            • 最终集成E-R图如下:(图未给出)

7.4 逻辑结构设计

  1. 定义:逻辑结构设计的任务是把概念结构设计阶段设计好的基本E-R图转换为与选用数据库管理系统产品所支持的数据模型相符合的逻辑结构。

  2. E-R图向关系模型的转换

    • 转换原则:一个实体型转换为一个关系模式。关系的属性为实体的属性,关系的码为实体的码。

    • 实体型间的联系不同情况的转换方法

      • 一个1:1联系

        • 可以转换为一个独立的关系模式,也可以与任意一端对应的关系模式合并。

        • 转换为一个独立的关系模式

          • 关系的属性:与该联系相连的各实体的码及联系本身的属性。

          • 关系的候选码:每个实体的码均是该关系的候选码。

        • 与某一端实体对应的关系模式合并

          • 合并后关系的属性:加入对应关系的码和联系本身的属性。

          • 合并后关系的码:不变。

      • 一个1:n联系

        • 可以转换为一个独立的关系模式,也可以与n端对应的关系模式合并。

        • 转换为一个独立的关系模式

          • 关系的属性:与该联系相连的各实体的码及联系本身的属性。

          • 关系的候选码:n端实体的码。

        • 与n端对应的关系模式合并

          • 合并后关系的属性:在n端关系中加入1端关系的码和联系本身的属性。

          • 合并后关系的码:不变。

          • 该方法可以减少系统中的关系个数,一般情况下更倾向于采用这种方法。

      • 一个m:n联系:转换为一个关系模式。

        • 关系的属性:与该联系相连的各实体的码及联系本身的属性。

        • 关系的候选码:各实体码的组合。

        • :“选修”联系是一个m:n联系,可以将它转换为如下关系模式,其中学号与课程号为关系的组合码:选修(学号,课程号,成绩)

      • 三个或三个以上实体间的一个多元联系:转换为一个关系模式。

        • 关系的属性:与该联系相连的各实体的码及联系本身的属性。

        • 关系的候选码:各实体码的组合。

      • 具有相同码的关系模式可合并

        • 目的:减少系统中的关系个数。

        • 合并方法

          • 第一步:将其中一个关系模式的全部属性加入到另一个关系模式中。

          • 第二步:去掉其中的同义属性(可能同名也可能不同名)。

          • 第三步:适当调整属性的次序。

        • :将下面E-R图转换为关系模型,关系的码用下横线标出。(图未给出)

          • 部门(部门号,部门名,经理的职工号,…)

          • 职工(职工号,部门号,职工名,职务,…)

          • 产品(产品号,产品名,产品组长的职工号,…)

          • 供应商(供应商号,姓名,…)

          • 零件(零件号,零件名,…)

          • 职工工作(职工号,产品号,工作天数,…)

          • 供应(产品号,供应商号,零件号,供应量)

  3. 数据模型的优化

    • 目的:数据库逻辑设计的结果不是唯一的。为了进一步提高数据库应用系统的性能,还应该适当地修改、调整数据模型的结构,这就是数据模型的优化。

    • 优化方法

      • 确定数据依赖:按需求分析阶段所得到的语义,分别写出每个关系模式内部各属性之间的数据依赖以及不同关系模式属性之间数据依赖。

      • 极小化处理:对于各个关系模式之间的数据依赖进行极小化处理,消除冗余的联系。

      • 范式分析:按照数据依赖的理论对关系模式进行分析,考察是否存在部分函数依赖、传递函数依赖、多值依赖等,确定各关系模式分别属于第几范式。

      • 应用需求分析:按照需求分析阶段得到的各种应用对数据处理的要求,分析对于这样的应用环境这些模式是否合适,确定是否要对它们进行合并或分解。

      • 说明:并不是规范化程度越高的关系就越优。例如当查询经常涉及两个或多个关系模式的属性时,系统必须经常地进行连接运算,代价相当高,因此在这种情况下,第二范式甚至第一范式也许是适合的。

      • 关系模式的分解:对关系模式进行必要分解,提高数据操作效率和存储空间的利用率。

        • 常用分解方法

          • 水平分解:把(基本)关系的元组分为若干子集合,定义每个子集合为一个子关系。

            • 分解方法

              • 一是对符合80/20的,把经常使用的数据(约20%)水平分解出来,形成一个子关系。

              • 二是使每个事务存取的数据对应一个子关系。

          • 垂直分解:把关系模式R的属性分解为若干子集合,形成若干子关系模式。

            • 分解原则:经常在一起使用的属性从R中分解出来形成一个子关系模式。

            • 分解优点:可以提高某些事务的效率。

            • 分解缺点:可能使另一些事务不得不执行连接操作,降低了效率。

            • 适用范围:取决于分解后R上的所有事务的总效率是否得到了提高。

            • 分解方法

              • 简单情况直观分解。

              • 复杂情况用第6章中的模式分解算法。

            • 垂直分解的要求:垂直分解必须不损失关系模式的语义(保持无损连接性和保持函数依赖)。

  4. 设计用户子模式

    • 定义数据库模式的出发点:定义数据库模式主要是从系统的时间效率、空间效率、易维护等角度出发。

    • 定义用户外模式的考虑因素:定义用户外模式时应该更注重考虑用户的习惯与方便。包括三个方面:

      • (1)使用更符合用户习惯的别名 合并各分E-R图曾做了消除命名冲突的工作,以使数据库系统中同一关系和属性具有唯一的名字。用视图机制可以在设计用户视图时可以重新定义某些属性名,使其与用户习惯一致,方便使用。

        (2)针对不同级别的用户定义不同的视图,以保证系统的安全性。 假设有关系模式产品(产品号,产品名,规格,单价,生产车间,生产负责人,产品成本,产品合格率,质量等级),可以在产品关系上建立两个视图: 为一般顾客建立视图: 产品1(产品号,产品名,规格,单价) 为产品销售部门建立视图: 产品2(产品号,产品名,规格,单价,车间,生产负责人)

        (3)简化用户对系统的使用 如果某些局部应用中经常要使用某些很复杂的查询,为了方便用户,可以将这些复杂查询定义为视图。

7.5 数据库的物理设计

  1. 定义

    • 数据库在物理设备上的存储结构与存取方法称为数据库的物理结构,它依赖于选定的数据库管理系统。

    • 为一个给定的逻辑数据模型选取一个最适合应用要求的物理结构的过程,就是数据库的物理设计。

  2. 数据库物理设计的步骤

    • 确定数据库的物理结构:在关系数据库中主要指存取方法和存储结构。

    • 对物理结构进行评价:评价的重点是时间和空间效率。若评价结果满足原设计要求,则可进入到物理实施阶段。否则,就要重新设计或修改物理结构,有时甚至要返回逻辑设计阶段修改数据模型。

  3. 数据库物理设计的内容和方法

    • 设计物理数据库结构的准备工作

      • 充分了解应用环境,详细分析要运行的事务,以获得选择物理数据库设计所需参数。

      • 充分了解所用关系型数据库管理系统的内部特征,特别是系统提供的存取方法和存储结构。

    • 选择物理数据库设计所需参数

      • 对于数据库查询事务,需要得到以下信息:

        • 查询的关系。

        • 查询条件所涉及的属性。

        • 连接条件所涉及的属性。

        • 查询的投影属性。

      • 对于数据更新事务,需要得到以下信息:

        • 被更新的关系。

        • 每个关系上的更新操作条件所涉及的属性。

        • 修改操作要改变的属性值。

      • 每个事务在各关系上运行的频率和性能要求。

  4. 关系模式存取方法选择

    • 数据库系统是多用户共享的系统,对同一个关系要建立多条存取路径才能满足多用户的多种应用要求。

    • 物理结构设计的任务之一是根据关系数据库管理系统支持的存取方法确定选择哪些存取方法。

    • 数据库管理系统常用存取方法:

      • B+树索引存取方法。

      • Hash索引存取方法。

      • 聚簇存取方法。

    • B+树索引存取方法的选择

      • 选择索引存取方法实际上就是根据应用要求确定对哪些属性列建立索引、对哪些属性列建立组合索引、对哪些索引要设计为唯一索引等。

      • 选择索引存取方法的一般规则:

        • 如果一个(或一组)属性经常在查询条件中出现,则考虑在这个(或这组)属性上建立索引(或组合索引)。

        • 如果一个属性经常作为最大值和最小值等聚集函数的参数,则考虑在这个属性上建立索引。

        • 如果一个(或一组)属性经常在连接操作的连接条件中出现,则考虑在这个(或这组)属性上建立索引。

    • Hash存取方法的选择

      • 选择Hash存取方法的规则:如果一个关系的属性主要出现在等值连接条件中或主要出现在等值比较选择条件中,而且满足下列两个条件之一:

        • 该关系的大小可预知,而且不变。

        • 该关系的大小动态改变,但所选用的数据库管理系统提供了动态Hash存取方法。

    • 聚簇存取方法的选择

      • 聚簇是为了提高某个属性(或属性组)的查询速度,把这个或这些属性(称为聚簇码)上具有相同值的元组集中存放在连续的物理块中称为聚簇。

      • 说明

        • 聚簇对于某些类型的查询,可以提高查询效率。

        • 在一个基本表上最多只能建立一个聚簇索引。

        • 聚簇索引的适用条件,一是很少对基表进行增删操作,二是很少对其中的变长列进行修改操作。

      • :假设学生关系按所在系建有索引,现在要查询信息系的所有学生名单。

        • 信息系的500名学生分布在500个不同的物理块上时,至少要执行500次I/O操作。如果将同一系的学生元组集中存放,则每读一个物理块可得到多个满足查询条件的元组,从而显著地减少了访问磁盘的次数。

      • 选择聚簇存取方法

        • 设计候选聚簇

          • 常在一起进行连接操作的关系可以建立组合聚簇。

          • 如果一个关系的一组属性经常出现在相等比较条件中,则该单个关系可建立聚簇。

          • 如果一个关系的一个(或一组)属性上的值重复率很高,则此单个关系可建立聚簇。

        • 检查候选聚簇中的关系,取消其中不必要的关系

          • 从聚簇中删除经常进行全表扫描的关系。

          • 从聚簇中删除更新操作远多于连接操作的关系。

          • 从聚簇中删除重复出现的关系。当一个关系同时加入多个聚簇时,必须从这多个聚簇方案(包括不建立聚簇)中选择一个较优的,即在这个聚簇上运行各种事务的总代价最小。

  5. 确定数据库的存储结构

    • 确定数据库物理结构主要指确定数据的存放位置和存储结构,包括:确定关系、索引、聚簇、日志、备份等的存储安排和存储结构,确定系统配置等。

    • 确定数据的存放位置和存储结构要综合考虑存取时间、存储空间利用率和维护代价3个方面的因素。

    • 确定数据的存放位置

      • 根据应用情况将易变部分与稳定部分分开存放、经常存取部分与存取频率较低部分分开存放。

      • :可以将比较大的表分别放在两个磁盘上,以加快存取速度,这在多用户环境下特别有效。可以将日志文件与数据库对象(表、索引等)放在不同的磁盘以改进系统的性能。

    • 确定系统配置

      • 数据库管理系统一般都提供了一些系统配置变量和存储分配参数,初始情况下,系统都为这些变量赋予了合理的缺省值,在进行物理设计时需要根据应用环境确定这些参数值,使系统性能最优。

      • 系统配置变量很多,例如:同时使用数据库的用户数、同时打开的数据库对象数、内存分配参数、缓冲区分配参数(使用的缓冲区长度、个数)、存储分配参数、物理块的大小、物理块装填因子、时间片大小、数据库的大小、锁的数目等。

  6. 评价物理结构

    • 对数据库物理设计过程中产生的多种方案进行评价,从中选择一个较优的方案作为数据库的物理结构。

    • 评价方法主要是定量估算各种方案的存储空间、存取时间、维护代价,对估算结果进行权衡、比较,选择出一个较优的合理的物理结构。

7.6 数据库的实施和维护

  1. 数据的载入和应用程序的调试

    • 数据的载入

      • 数据库结构建立好后,就可以向数据库中装载数据了。组织数据入库是数据库实施阶段最主要的工作。

      • 数据装载方法:人工方法、计算机辅助数据入库。

    • 应用程序的调试

      • 数据库应用程序的设计应该与数据设计并行进行,在组织数据入库的同时还要调试应用程序。

  2. 数据库的试运行

    • 应用程序调试完成,并且已有一小部分数据入库后,就可以开始对数据库系统进行联合调试,也称数据库的试运行。

    • 主要工作包括:

      • 功能测试:实际运行应用程序,执行对数据库的各种操作,测试应用程序的各种功能。

      • 性能测试:测量系统的性能指标,分析是否符合设计目标。

      • 说明

        • 数据的分期入库。

        • 做好数据库的转储和恢复。

  3. 数据库的运行和维护

    • 在数据库运行阶段,对数据库经常性的维护工作主要是由数据库管理员完成。

    • 主要工作包括:

      • 数据库的转储和恢复

        • 数据库管理员要针对不同的应用要求制定不同的转储计划,一旦发生介质故障,尽快将数据库恢复到某种一致性状态。

      • 数据库的安全性、完整性控制

        • 当应用环境发生变化,对安全性的要求也会发生变化,数据库管理员需要根据实际情况修改原有的安全性控制,同样数据库的完整性约束条件也会变化。

      • 数据库性能的监督、分析和改进

        • 在数据库运行过程中,数据库管理员必须监督系统运行,对监测数据进行分析,找出改进系统性能的方法。

      • 数据库的重组织与重构造

        • 数据库的重组织

          • 数据库运行一段时间后,由于记录的不断增、删、改,会使数据库的物理存储变坏,从而降低数据库存储空间的利用率和数据的存取效率,使数据库的性能下降。

          • 数据库的重组织不会改变原设计的数据逻辑结构和物理结构。

          • 重组织的方法:按原设计要求重新安排存储位置、回收垃圾、减少指针链。

        • 数据库的重构造

          • 数据库应用环境发生变化,会导致实体及实体间的联系也发生相应的变化,使原有的数据库设计不能很好地满足新的需求。

          • 数据库的重构造需根据新环境调整数据库的模式和内模式。

          • 重构造的方法:增加或删除某些数据项、改变数据项的类型、增加或删除某个表、改变数据库的容量、增加或删除某些索引等。

          • 若应用变化太大,已无法通过重构数据库来满足新的需求,或重构数据库的代价太大,则表明现有数据库应用系统的生命周期已经结束,应该重新设计新的数据库应用系统了。

7.7 小结

  1. 数据库设计的方法和步骤。

  2. 数据库设计6个阶段,重点是概念结构的设计和逻辑结构的设计。

  3. 概念结构的设计:

    • 概念结构的设计着重介绍了E-R模型的基本概念和图示方法。

    • 应重点掌握实体型、属性和联系的概念,理解实体型之间的一对一、一对多和多对多联系。

    • 掌握E-R模型的设计以及把E-R模型转换为关系模型的方法。

  4. 逻辑结构的设计:

    • 将概念结构转化为具体的数据模型。

第8章 数据库编程

8.1 嵌入式SQL

8.1.1 嵌入式SQL的处理过程

  • 主语言:嵌入式SQL是将SQL语句嵌入程序设计语言中,被嵌入的程序设计语言(如C、C++、Java)称为宿主语言,简称主语言。

  • 嵌入式SQL前缀:为了区分SQL语句与主语言语句,所有SQL语句必须加前缀。

    • 主语言为C语言时,语句格式:EXEC SQL <SQL语句>;

    • 主语言为Java语言时,语句格式:#SQL <SQL语句>;

  • 嵌入式SQL处理过程:采用预编译方法,关系数据库管理系统预处理程序将嵌入式SQL语句转换为函数调用,然后由主语言编译程序进行编译处理,最终生成目标语言程序。

8.1.2 嵌入式SQL语句与主语言之间的通信

  • SQL通信区(SQLCA)

    • 用途:SQL语句执行后,系统将描述系统当前工作状态的数据和描述运行环境的数据送到SQL通信区中,应用程序从SQL通信区中取出这些状态信息,据此决定接下来执行的语句。

    • 定义格式:EXEC SQL INCLUDE SQLCA;

    • 说明:

      • SQLCA中设置变量SQLCODE,存放每次执行SQL语句后返回代码。

      • 当SQLCODE等于SUCCESS,表示SQL语句成功,否则出错。

      • 应用程序每执行完一条SQL语句都应该测试一下SQLCODE的值,以了解该SQL语句执行情况并做相应处理。

  • 主变量

    • 嵌入式SQL语句中可以使用主语言的程序变量来输入或输出数据,在SQL语句中使用的主语言程序变量,简称为主变量。

    • 输入主变量:由应用程序对其赋值,SQL语句引用。

    • 输出主变量:由SQL语句对其赋值或设置状态信息,返回给应用程序。

    • 指示变量:是一个整型变量,一个主变量可以附带一个指示变量,用来指示所指主变量的值或条件,例如指示变量的用途、指示输入主变量是否为空值、检测输出变量是否为空值、值是否被截断等。

    • 定义格式:

      sql复制

      BEGIN DECLARE SECTION
      ...
      ... (说明主变量和指示变量)
      ...
      END DECLARE SECTION
    • 说明:

      • 定义的主变量可以在SQL语句中任何一个能够使用表达式的地方出现。

      • 为了与数据库对象名(表名、视图名、列名等)区别,SQL语句中的主变量名前要加冒号(:)作为标志。

      • 指示变量必须紧跟在所指主变量之后,指示变量前也必须加冒号标志。

      • 在SQL语句之外(主语言语句中)可以直接引用主变量和指示变量,不必加冒号。

  • 游标

    • 为什么要使用游标:SQL语言是面向集合的,一条SQL语句原则上可以产生或处理多条记录。主语言是面向记录的,一组主变量一次只能存放一条记录。仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求。嵌入式SQL引入了游标的概念,用来协调这两种不同的处理方式。

    • 什么是游标:游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。

  • 建立和关闭数据库连接

    • 建立数据库连接

      • 格式:EXEC SQL CONNECT TO target[AS connection name][USER user-name];

      • 说明:

        • target是要连接的数据库服务器,常见的如:包含服务器标识的SQL串常量、<dbname>@<hostname>:<port>DEFAULT

        • connection-name指定的连接名。连接名必须是一个有效的标识符。如果在整个程序内只有一个连接时可以不指定连接名。

        • 程序运行过程中可以用以下语句修改当前连接:EXEC SQL SET CONNECTION connection-name|DEFAULT;

    • 关闭数据库连接

      • 格式:EXEC SQL DISCONNECT [connection];

      • 说明:connection是用EXEC SQL CONNECT所建立的数据库连接。

8.1.3 不用游标的SQL语句

  • 说明性语句

  • 数据定义语句

  • 数据控制语句

  • 查询结果为单记录的SELECT语句

    • 这类语句不需要使用游标,只需用INTO子句指定存放查询结果的主变量。

    • 示例:根据学生号码查询学生信息。

      sql复制

      EXEC SQL SELECT Sno, Sname, Ssex, Sage, Sdept
      INTO :Hsno, :Hname, :Hsex, :Hage, :Hdept
      FROM Student
      WHERE Sno = :givensno;
    • 说明:

      • INTO子句、WHERE子句和HAVING短语的条件表达式中均可以使用主变量。

      • 查询结果的列为空值NULL,系统会自动将主变量后的指示变量设置为负值,当指示变量为负值时,不管主变量为何值,系统均认为主变量为NULL。

      • 如果查询结果实际上是多条记录,则程序出错,关系数据库管理系统会在SQLCA中返回错误信息。

    • 示例:查询某个学生选修某门课程的成绩。假设已经把将要查询的学生的学号赋给了主变量givensno,将课程号赋给了主变量givencno

      sql复制

      EXEC SQL SELECT Sno, Cno, Grade
      INTO :Hsno, :Hcno, :Hgrade :Gradeid /*指示变量Gradeid*/
      FROM SC
      WHERE Sno = :givensno AND Cno = :givencno;

      如果Gradeid < 0,不论Hgrade为何值,均认为该学生成绩为空值。

  • 非CURRENT形式的增删改语句

    • UPDATESET子句和WHERE子句中可以使用主变量,SET子句还可以使用指示变量。

    • 示例:修改某个学生选修1号课程的成绩。

      sql复制

      EXEC SQL UPDATE SC
      SET Grade = :newgrade
      WHERE Sno = :givensno;
    • 示例:某个学生新选修了某门课程,将有关记录插入SC表中。假设插入的学号已赋给主变量stdno,课程号已赋给主变量couno

      sql复制

      gradeid = -1; /*gradeid为指示变量,赋为负值*/
      EXEC SQL INSERT
      INTO SC(Sno, Cno, Grade)
      VALUES(:stdno, :couno, :gr :gradeid);

      由于该学生刚选修课程,成绩应为空,所以要把指示变量赋为负值。

8.1.4 使用游标的SQL语句

  • 必须使用游标的SQL语句

    • 查询结果为多条记录的SELECT语句。

    • CURRENT形式的UPDATE语句。

    • CURRENT形式的DELETE语句。

  • 查询结果为多条记录的SELECT语句

    • 使用游标的步骤:

      1. 说明游标

        • 语句格式:EXEC SQL DECLARE <游标名> CURSOR FOR <SELECT语句>;

        • 功能:该语句是一条说明性语句,这时关系数据库管理系统并不执行SELECT语句。

      2. 打开游标

        • 语句格式:EXEC SQL OPEN <游标名>;

        • 功能:执行相应的SELECT语句,把查询结果取到缓冲区中,这时游标处于活动状态,指针指向查询结果集中的第一条记录。

      3. 推进游标指针并取当前记录

        • 语句格式:EXEC SQL FETCH <游标名> INTO <主变量>[<指示变量>][, <主变量>[<指示变量>]]…;

        • 功能:指定方向推动游标指针,同时将缓冲区中的当前记录取出来送至主变量供主语言进一步处理。

      4. 关闭游标

        • 语句格式:EXEC SQL CLOSE <游标名>;

        • 功能:关闭游标,释放结果集占用的缓冲区及其他资源。

    • 说明:

      • 游标被关闭后,就不再和原来的查询结果集相联系。

      • 被关闭的游标可以再次被打开,与新的查询结果相联系。

  • CURRENT形式的UPDATE语句和DELETE语句

    • 如修改或删除某个记录,用带游标的SELECT语句查出满足条件的集合,从中进一步找出要修改或删除的记录,用CURRENT形式的UPDATE语句和DELETE语句修改或删除之。

    • UPDATE语句和DELETE语句中要用子句:WHERE CURRENT OF <游标名>,表示修改或删除游标指针指向的记录。

    • 注意:游标定义中的SELECT语句带有UNIONORDER BY子句,或者该SELECT语句相当于定义了一个不可更新的视图,则不能使用CURRENT形式的UPDATE语句和DELETE语句。

8.1.5 动态SQL

  • 静态嵌入式SQL:静态嵌入式SQL语句能够满足一般要求,无法满足要到执行时才能够确定要提交的SQL语句、查询的条件。

  • 动态嵌入式SQL:在程序运行过程中可临时“组装”SQL语句,支持动态组装SQL语句和动态参数两种形式。

    • 使用SQL语句主变量

      • SQL语句主变量:程序主变量包含的内容是SQL语句的内容,而不是原来保存数据的输入或输出变量。

      • SQL语句主变量在程序执行期间可以设定不同的SQL语句,然后立即执行。

      • 示例:创建基本表TEST

        sql复制

        EXEC SQL BEGIN DECLARE SECTION;
        const char *stmt = "CREATE TABLE test(a int);";
        /*SQL语句主变量,内容是创建表的SQL语句*/
        EXEC SQL END DECLARE SECTION;
        ...
        EXEC SQL EXECUTE IMMEDIATE :stmt; /*执行动态SQL语句*/
    • 动态参数

      • 动态参数是SQL语句中的可变元素,使用参数符号(?)表示该位置的数据在运行时设定。

      • 与主变量不同,动态参数的输入不是编译时完成绑定,而是通过PREPARE语句准备主变量和执行语句EXECUTE绑定数据或主变量来完成。

      • 使用动态参数的步骤:

        1. 声明SQL语句主变量:SQL语句主变量的值包含动态参数(?)。

        2. 准备SQL语句(PREPARE

          sql复制

          EXEC SQL PREPARE <语句名> FROM <SQL语句主变量>;
        3. 执行准备好的语句(EXECUTE

          sql复制

          EXEC SQL EXECUTE <语句名>
          [INTO <主变量表>][USING <主变量或常量>];
      • 示例:向TEST中插入元组。

        sql复制

        EXEC SQL BEGIN DECLARE SECTION;
        const char *stmt = "INSERT INTO test VALUES(?);";
        /*声明SQL主变量内容是INSERT语句 */
        EXEC SQL END DECLARE SECTION;
        ...
        EXEC SQL PREPARE mystmt FROM :stmt; /*准备语句*/
        ...
        EXEC SQL EXECUTE mystmt USING 100;
        EXEC SQL EXECUTE mystmt USING 200;

8.2 过程化SQL

8.2.1 过程化SQL的块结构

  • 过程化SQL:过程化SQL是SQL的扩展,增加了过程化语句功能,基本结构是块,每个块完成一个逻辑操作,块之间可以互相嵌套。

  • 过程化SQL块的基本结构

    1. 定义部分

      • DECLARE:定义的变量、常量等只能在该基本块中使用。

      • 变量、常量、游标、异常等:当基本块执行结束时,定义就不再存在。

    2. 执行部分

      • BEGIN

        • SQL语句、过程化SQL的流程控制语句

      • EXCEPTION

        • 异常处理部分

      • END;

8.2.2 变量和常量的定义

  • 变量定义

    • 变量名 数据类型 [[NOT NULL]:=初值表达式]

    • 变量名 数据类型 [[NOT NULL] 初值表达式]

  • 常量定义

    • 常量名 数据类型 CONSTANT:=常量表达式

    • 常量必须要给一个值,并且该值在存在期间或常量的作用域内不能改变。如果试图修改它,过程化SQL将返回一个异常。

  • 赋值语句

    • 变量名称:=表达式

8.2.3 流程控制

  • 条件控制语句

    • IF-THEN

      • 语句格式:

        sql复制

        IF 条件 THEN
        语句;
        END IF;
    • IF-THEN-ELSE

      • 语句格式:

        sql复制

        IF 条件 THEN
        条件为真时执行的语句;
        ELSE
        条件为假或NULL时执行的语句;
        END IF;
    • 嵌套的IF语句:在THEN和ELSE子句中还可以再包含IF语句,即IF语句可以嵌套。

  • 循环控制语句

    • 简单的循环语句LOOP

      • 格式:

        sql复制

        LOOP
        循环执行的语句;
        END LOOP;
      • 多数数据库服务器的过程化SQL都提供EXIT、BREAK或LEAVE等循环结束语句,保证LOOP语句块能够结束。

    • WHILE-LOOP循环

      • 格式:

        sql复制

        WHILE 条件 LOOP
        条件为真时执行的语句;
        END LOOP;
      • 执行过程:每次执行循环体语句之前,首先对条件进行求值,如果条件为真,则执行循环体内的语句序列,如果条件为假,则跳过循环并把控制传递给下一个语句。

    • FOR-LOOP循环

      • 格式:

        sql复制

        FOR 循环变量 IN [REVERSE] bound1 ... bound2 LOOP
        循环语句;
        END LOOP;
      • 执行过程:循环变量设置为下界bound1,检查循环变量是否小于上界bound2,如果是执行循环体,循环变量加1,如果否,退出循环。当设置REVERSE,表示bound1为上界,bound2为下界,循环变量减1。

  • 错误处理

    • 如果过程化SQL在执行时出现异常,则应该让程序在产生异常的语句处停下来,根据异常的类型去执行异常处理语句。

    • SQL标准对数据库服务器提供什么样的异常处理做出了建议,要求过程化SQL管理器提供完善的异常处理机制。

8.3 存储过程和函数

8.3.1 存储过程

  • 存储过程:由过程化SQL语句书写的过程,经编译和优化后存储在数据库服务器中,使用时只要调用即可。

  • 存储过程的优点

    1. 运行效率高。

    2. 降低了客户机和服务器之间的通信量。

    3. 方便实施企业规则。

  • 存储过程的用户接口

    • 创建存储过程格式

      CREATE OR REPLACE PROCEDURE 过程名([参数1, 参数2, ...])
      AS <过程化SQL块>;
      • 说明:

        • 过程名:数据库服务器合法的对象标识。

        • 参数列表:用名字来标识调用时给出的参数值,必须指定值的数据类型。参数也可以定义输入参数、输出参数或输入/输出参数,默认为输入参数。

        • 过程体:是一个<过程化SQL块>,包括声明部分和可执行语句部分。

      • 示例:利用存储过程来实现下面的应用:从账户1转指定数额的款项到账户2中。

        CREATE OR REPLACE PROCEDURE TRANSFER(inAccount INT, outAccount INT, amount FLOAT)
        /*定义存储过程TRANSFER,参数为转入账户、转出账户、转账额度*/
        AS DECLARE /*定义变量*/
        totalDepositOut Float;
        totalDepositIn Float;
        inAccountnum INT;
        BEGIN /*检查转出账户的余额 */
        SELECT Total INTO totalDepositOut FROM Account
        WHERE accountnum = outAccount;
        IF totalDepositOut IS NULL THEN
        /*如果转出账户不存在或账户中没有存款*/
        ROLLBACK; /*回滚事务*/
        RETURN;
        END IF;
        IF totalDepositOut < amount THEN /*账户存款不足*/
        ROLLBACK; /*回滚事务*/
        RETURN;
        END IF;
        SELECT Accountnum INTO inAccountnum FROM Account
        WHERE accountnum = inAccount;
        IF inAccount IS NULL THEN /*转入账户不存在*/
        ROLLBACK; /*回滚事务*/
        RETURN;
        END IF;
        UPDATE Account SET total = total - amount WHERE
        accountnum = outAccount;
        /* 修改转出账户余额,减去转出额 */
        UPDATE Account SET total = total + amount WHERE
        accountnum = inAccount;
        /* 修改转入账户余额,增加转入额 */
        COMMIT; /* 提交转账事务 */
        END;
    • 执行存储过程

      CALL/PERFORM PROCEDURE 过程名([参数1, 参数2, ...]);
      • 说明:使用CALL或者PERFORM等方式激活存储过程的执行,在过程化SQL中,数据库服务器支持在过程体中调用其他存储过程。

      • 示例:从账户01003813828转10000元到01003815868账户中。

        CALL PROCEDURE TRANSFER(01003813828, 01003815868, 10000);
    • 修改存储过程

      ALTER PROCEDURE 过程名1 RENAME TO 过程名2;
    • 删除存储过程

      DROP PROCEDURE 过程名();

8.3.2 函数

  • 函数:本章所讲的函数是用户自定义函数,函数和存储过程类似都是持久性存储模块,不同的是函数必须指定返回的类型。

  • 函数的定义语句格式

    CREATE OR REPLACE FUNCTION 函数名 ([参数1, 参数2, ...])
    RETURNS <类型> AS <过程化SQL块>;
  • 函数的执行语句格式

    CALL/SELECT 函数名 ([参数1, 参数2, ...]);
  • 修改函数

    • 重命名

      ALTER FUNCTION 函数名1 RENAME TO 函数名2;
    • 重新编译

      ALTER FUNCTION 函数名 COMPILE;
  • 过程化SQL中的游标

    • 在过程化SQL中如果查询返回多条记录时,就要使用游标对结果集进行处理。在存储过程中可以定义普通游标、REFCURSOR类型游标、带参数游标等。

    • 示例:定义存储过程,多次打开游标并获取游标当前记录。

      CREATE OR REPLACE PROCEDURE pro_cursor() AS
      DECLARE
      cno CHAR(3);
      cname CHAR(8);
      CURSOR mycursor(leaderno CHAR(3)) FOR /*说明带参数游标mycursor*/
      SELECT lno, lname FROM leader WHERE lno = leaderno;
      BEGIN
      /*mycursor能检索leader表中具有参数leaderno的记录*/
      OPEN mycursor('L01'); /*使用参数L01打开游标*/
      FETCH mycursor INTO cno, cname; /*获取lno='L01'的游标元组*/
      INSERT INTO temp(lno, lname) VALUES(cno, cname);
      /*将游标元组插入临时表中*/
      CLOSE mycursor;/*关闭游标*/
      OPEN mycursor('L02');/*使用新的参数L02重新打开游标*/
      FETCH mycursor INTO cno, cname;
      INSERT INTO temp(lno, lname) VALUES(cno, cname);
      CLOSE mycursor;
      END;

8.4 ODBC编程

8.4.1 ODBC概述

  • ODBC产生的原因

    1. 由于不同的数据库管理系统的存在,在某个关系数据库管理系统下编写的应用程序就不能在另一个关系数据库管理系统下运行。

    2. 许多应用程序需要共享多个部门的数据资源,访问不同的关系数据库管理系统。

  • 什么是ODBC

    • ODBC是微软公司开放服务体系中有关数据库的一个组成部分,它提供了一组访问数据库的应用程序编程接口(API)。

    • 主要作用是规范应用开发和规范关系数据库管理系统应用接口。

8.4.2 ODBC工作原理概述

  • ODBC应用系统的体系结构

    • 包括用户应用程序、ODBC驱动程序管理器、数据库驱动程序、数据源。

  • 用户应用程序

    • ODBC应用程序包括的内容:

      1. 请求连接数据库。

      2. 向数据源发送SQL语句。

      3. 为SQL语句执行结果分配存储空间,定义读取的数据格式。

      4. 获取数据库操作结果或处理错误。

      5. 进行数据处理并向用户提交处理结果。

      6. 请求事务的提交和回滚操作。

      7. 断开与数据源的连接。

  • ODBC驱动程序管理器

    • 驱动程序管理器包含在ODBC32.DLL中,对用户透明,管理应用程序和驱动程序之间的通信。

    • 主要功能:

      1. 装载ODBC驱动程序。

      2. 选择和连接正确的驱动程序。

      3. 管理数据源。

      4. 检查ODBC调用参数的合法性。

      5. 记录ODBC函数的调用等。

  • 数据库驱动程序

    • ODBC通过驱动程序来提供应用系统与数据库平台的独立性,ODBC应用程序不能直接存取数据库,各种操作由驱动程序提交给DBMS的ODBC驱动程序,调用驱动程序支持的函数来存取数据库。

    • ODBC驱动程序类型:

      • 单束:数据源和应用程序在同一台机器上,驱动程序直接完成对数据文件的I/O操作,驱动程序相当于数据管理器。

      • 多束:支持客户机—服务器、客户机—应用服务器/数据库服务器等网络环境下的数据访问,由驱动程序完成数据库访问请求的提交和结果集接收,应用程序使用驱动程序提供的结果集管理接口操纵执行后的结果数据。

  • ODBC数据源管理

    • 数据源:是最终用户需要访问的数据,包含了数据库位置和数据库类型等信息,是一种数据连接的抽象。

    • 说明:

      • ODBC给每个被访问的数据源指定唯一的数据源名(Data Source Name,简称DSN),并映射到所有必要的、用来存取数据的低层软件。

      • 在连接中,用数据源名来代表用户名、服务器名、所连接的数据库名等。用户无须知道数据库管理系统或其他数据管理软件、网络以及有关ODBC驱动程序的细节。

      • 示例:假设某个学校在SQL Server和KingbaseES上创建了两个数据库:学校人事数据库和教学科研数据库。学校的信息系统要从这两个数据库中存取数据,为了方便地与两个数据库连接,为学校人事数据库创建一个数据源名PERSON,为教学科研数据库创建一个名为EDU的数据源。当要访问每一个数据库时,只要与PERSON和EDU连接,不需要记住使用的驱动程序、服务器名称、数据库名。

8.4.3 ODBC API基础

  • 函数概述

    • ODBC 3.0标准提供了76个函数接口,大致可分为:

      1. 分配和释放环境句柄、连接句柄、语句句柄。

      2. 连接函数(SQLDriverconnect等)。

      3. 与信息相关的函数(SQLGetinfoSQLGetFuction等)。

      4. 事务处理函数(如SQLEndTran)。

      5. 执行相关函数(SQLExecdirectSQLExecute等)。

      6. 编目函数,ODBC 3.0提供了11个编目函数,如SQLTablesSQLColumn等。

  • 句柄及其属性

    • 句柄是32位整数值,代表一个指针。ODBC 3.0中句柄分为环境句柄、连接句柄、语句句柄、描述符句柄。具体关系如下图:

      ODBC应用程序
      环境句柄
      连接句柄
      语句句柄 数据源 描述符句柄
      1 1
      1 n
      1 n
      1
      1
      1
      n
    • 说明:

      • 每个ODBC应用程序需要建立一个ODBC环境,分配一个环境句柄,存取数据的全局性背景,如环境状态、当前环境状态诊断、当前在环境上分配的连接句柄等。

      • 一个环境句柄可以建立多个连接句柄,每一个连接句柄实现与一个数据源之间的连接。

      • 在一个连接中可以建立多个语句句柄,它不只是一个SQL语句,还包括SQL语句产生的结果集以及相关的信息等。

      • 在ODBC 3.0中又提出了描述符句柄的概念,它是描述SQL语句的参数、结果集列的元数据集合。

  • 数据类型

    • ODBC数据类型:SQL数据类型用于数据源;C数据类型用于应用程序的C代码。

    • 应用程序可以通过SQLGetTypeInfo来获取不同的驱动程序对于数据类型的支持情况。

    • SQL数据类型和C数据类型之间的转换规则。

8.4.4 ODBC的工作流程

  • 示例:将KingbaseES数据库中Student表的数据备份到SQL Server数据库中。

    • 该应用涉及两个不同的关系数据库管理系统中的数据源,使用ODBC来开发应用程序,只要改变应用程序中连接函数(SQLConnect)的参数,就可以连接不同关系数据库管理系统的驱动程序,连接两个数据源。

  • 配置数据源

    • 配置数据源有两种方法:

      1. 运行数据源管理工具来进行配置。

      2. 使用Driver Manager提供的ConfigDsn函数来增加、修改或删除数据源。

    • 上例中,采用第一种方法创建数据源。因为要同时用到KingbaseES和SQL Server,所以分别建立两个数据源,将其取名为KingbaseES ODBC和SQL Server。

  • 初始化环境

    • 没有和具体的驱动程序相关联,由Driver Manager来进行控制,并配置环境属性。应用程序通过调用连接函数和某个数据源进行连接后,Driver Manager才调用所连的驱动程序中的SQLAllocHandle,来真正分配环境句柄的数据结构。

  • 建立连接

    • 应用程序调用SQLAllocHandle分配连接句柄,通过SQLConnectSQLDriverConnectSQLBrowseConnect与数据源连接。

  • 分配语句句柄

    • 处理任何SQL语句之前,应用程序还需要首先分配一个语句句柄,语句句柄含有具体的SQL语句以及输出的结果集等信息。

  • 执行SQL语句

    • 处理SQL语句的两种方式:

      • 预处理(SQLPrepareSQLExecute适用于语句的多次执行)。

      • 直接执行(SQLExecdirect)。

    • 应用程序根据语句类型进行的处理:

      • 有结果集的语句则进行结果集处理。

      • 没有结果集的函数,可以直接利用本语句句柄继续执行新的语句或是获取行计数(本次执行所影响的行数)之后继续执行。

  • 结果集处理

    • 应用程序可以通过SQLNumResultCols来获取结果集中的列数。

    • 通过SQLDescribeCol或是SQLColAttribute函数来获取结果集每一列的名称、数据类型、精度和范围。

    • ODBC中使用游标来处理结果集数据,ODBC中游标类型有:

      • Forward-only游标(ODBC的默认游标类型):只能在结果集中向前滚动,它是ODBC的默认游标类型。

      • 可滚动(Scroll)游标:静态、动态、码集驱动、混合型。

  • 中止处理

    • 处理结束后,应用程序首先释放语句句柄,然后释放数据库连接并与数据库服务器断开,最后释放ODBC环境。

*8.5 OLE DB

  • 什么是OLE DB

    • OLE DB对象链接与嵌入式数据库,是微软提出的数据库访问标准。是基于组件对象模型(COM)来访问各种数据源的ActiveX的通用接口。

    • OLE DB可以连接数据库,也可以是文本文件、Excel表格等各种不同格式的数据存储。

  • OLE DB的结构

    • OLE DB中包括了消费者和提供者。

      • 消费者:利用OLE DB提供的接口访问数据库数据的客户端应用程序或其他工具。

      • 提供者:提供者是一个由COM组件构成的数据访问中介,位于数据库和消费者之间。

        • 服务提供者:这类提供者自身没有数据,它通过OLE DB接口封装服务,从下层获取数据并向上层提供数据,具有提供者和消费者双重身份。

        • 数据提供者:数据提供者自己拥有数据并通过接口形成表格形式的数据。

  • OLE DB编程模型

    • 数据管理任务必须由消费者访问数据,由提供者发布数据。

    • OLE DB编程模型分类:

      • Rowset编程模型:假定数据源中的数据比较规范,提供者以行集形式发布数据。

      • Binder编程模型:提供者不提供标准表格式数据,OLE DB采用Binder编程模型将URL和一个OLE DB对象相关联或绑定,并在必要时创建层次结构的对象。

*8.6 JDBC编程

  • JDBC:是Java制定的数据库连接技术的简称,在应用程序中与ODBC类似,是JAVA实现数据库访问的应用程序编程接口。

  • JDBC编程

    • 是面向对象的接口标准,一般由具体数据库厂商提供。

    • 为JAVA提供统一、无缝地操作各种数据库的接口。

8.7 小结

  • 本章讲解了如何使用编程方法对数据库进行操纵的技术。

    1. 嵌入式SQL把SQL语言嵌入到高级语言中。

    2. SQL与主语言具有不同的数据处理方式。

    3. 过程化SQL编写存储过程和自定义函数。

    4. ODBC工作原理和工作流程。

第9章 关系查询处理和查询优化

9.1 关系数据库系统的查询处理

9.1.1 查询处理步骤

关系数据库管理系统查询处理分为以下步骤:

  1. 查询分析

    • 对查询语句进行扫描、词法分析和语法分析。

    • 词法分析:从查询语句中识别出正确的语言符号。

    • 语法分析:进行语法检查。

  2. 查询检查

    • 合法性检查:根据数据字典中有关的模式定义检查语句中的数据库对象,如关系名、属性名是否存在和有效。

    • 视图转换:如果是对视图的操作,则要用视图消解方法把对视图的操作转换成对基本表的操作。

    • 安全性和完整性初步检查:根据数据字典中的用户权限和完整性约束定义对用户的存取权限进行检查。

    • 检查通过后把SQL查询语句转换成内部表示,即等价的关系代数表达式。关系数据库管理系统一般都用查询树,也称为语法分析树来表示扩展的关系代数表达式。

  3. 查询优化

    • 查询优化即选择一个高效执行的查询处理策略。

    • 查询优化分类

      • 代数优化/逻辑优化:指关系代数表达式的优化,即按照一定的规则,通过对关系代数表达式进行等价变化,改变关系代数操作的次序和组合,使查询执行更高效。

      • 物理优化:指存取路径和底层操作算法的选择。

    • 查询优化的选择依据

      • 基于规则(rule based)

      • 基于代价(cost based)

      • 基于语义(semantic based)

  4. 查询执行

    • 依据优化器得到的执行策略生成查询执行计划,由代码生成器(code generator)生成执行查询计划的代码,然后执行这个查询计划,回送查询结果。

9.1.2 实现查询操作的算法示例

1. 选择操作的典型实现
  • 全表扫描方法(Table Scan)

    • 对查询的基本表顺序扫描,逐一检查每个元组是否满足选择条件,把满足条件的元组作为结果输出。该方法适合小表,不适合大表。

    • 算法思想:

      1. 按照物理次序读表的若干块到内存。

      2. 检查内存的每个元组,如果满足选择条件,则输出。

      3. 如果表还有其他块未被处理,重复上述步骤。

  • 索引扫描方法(Index Scan)

    • 适合于选择条件中的属性上有索引(例如B+树索引或Hash索引),通过索引先找到满足条件的元组主码或元组指针,再通过元组指针直接在查询的基本表中找到元组。

    • 示例:

      • SELECT * FROM Student WHERE Sno='201215121';(假设Sno上有索引)

      • SELECT * FROM Student WHERE Sage>20;(假设Sage上有B+树索引)

      • SELECT * FROM Student WHERE Sdept='CS' AND Sage>20;(假设Sdept和Sage上都有索引)

2. 连接操作的实现

连接操作是查询处理中最耗时的操作之一,本节只讨论等值连接(或自然连接)最常用的实现算法。

  • 嵌套循环算法(nested loop join)

    1. 对外层循环(表1)的每一个元组,检索内层循环(表2)中的每一个元组。

    2. 检查这两个元组在连接属性上是否相等。

    3. 如果满足连接条件,则串接后作为结果输出,直到外层循环表中的元组处理完为止。

  • 排序-合并算法(sort-merge join或merge join)

    1. 如果连接的表没有排好序,先对表按连接属性排序。

    2. 取表1中第一个连接属性值,依次扫描表2中具有相同连接属性值的元组。

    3. 当扫描到连接属性值不相同的第一个表2元组时,返回表1扫描它的下一个元组,再扫描表2中具有相同连接属性值的元组,把它们连接起来。

    4. 重复上述步骤直到表1扫描完。

  • 索引连接(index join)算法

    1. 在表2上已经建立连接属性的索引。

    2. 对表1中每一个元组,由连接属性值通过表2的索引查找相应的表2元组。

    3. 把这些表2元组和表1元组连接起来。

    4. 循环执行上述步骤,直到表1中的元组处理完为止。

  • Hash Join算法

    1. 把连接属性作为Hash码,用同一个Hash函数把表1和表2中的元组散列到Hash表中。

    2. 第一阶段(划分阶段):对包含较少元组的表进行一遍处理,把它的元组按Hash函数分散到Hash表的桶中。

    3. 第二阶段(试探阶段):对包含较多元组的表进行一遍处理,把表的元组也按同一个Hash函数进行散列,把与桶中来自表1并与之相匹配的元组连接起来。

    4. 算法前提:较小的表在第一阶段后可完全放入内存Hash桶中。


9.2 关系数据库系统的查询优化

9.2.1 查询优化概述

关系系统的查询优化是关系数据库管理系统实现的关键技术,也是关系系统的优点所在,减轻了用户选择存取路径的负担。用户只要提出“干什么”,不必指出“怎么干”。

非关系系统中,用户使用过程化的语言表达查询要求,执行何种记录级的操作以及操作的序列由用户决定。因此,用户必须了解存取路径,系统要提供用户选择存取路径的手段,查询效率由用户的存取策略决定,如果用户做了不当的选择,系统是无法对此加以改进的。

查询优化的优点不仅在于用户不必考虑如何最好地表达查询以获得较好的效率,还在于系统可比用户程序的“优化”做得更好。主要原因是:

  1. 优化器可以从数据字典中获取许多统计信息,而用户程序则难以获得这些信息。

  2. 如果数据库的物理统计信息改变了,系统可自动对查询重新优化以选择相适应的执行计划。在非关系系统中必须重写程序,而重写程序在实际应用中往往是不太可能的。

  3. 优化器可以考虑数百种不同的执行计划,程序员一般只能考虑有限的几种可能性。

  4. 优化器中包括了很多复杂的优化技术,这些优化技术往往只有最好的程序员才能掌握。系统的自动优化相当于使得所有人都拥有这些优化技术。

关系数据库管理系统通过某种代价模型计算出各种查询执行策略的执行代价,然后选取代价最小的执行方案。在集中式数据库中,执行代价主要包括磁盘存取块数(I/O代价)、处理机时间(CPU代价)、查询的内存开销,其中I/O代价是最主要的,因为I/O操作涉及机械动作。在分布式数据库中,执行代价还包括通信代价。

9.2.2 一个实例

一个关系查询可以对应不同的执行方案,其效率可能相差非常大。

示例:求选修了2号课程的学生姓名。

SELECT Student.Sname
FROM Student, SC
WHERE Student.Sno = SC.Sno AND SC.Cno = '2';

假定学生-课程数据库中有1000个学生记录,10000个选课记录,选修2号课程的选课记录为50个。

可以用多种等价的关系代数表达式来完成这一查询:

  • Q1 = πSname(σStudent.Sno=SC.Sno∧SC.Cno='2'(Student×SC))

  • Q2 = πSname(σSC.Cno='2'(Student ⋈ SC))

  • Q3 = πSname(Student ⋈ σSC.Cno='2'(SC))

第一种情况

Q1 = πSname(σStudent.Sno=SC.Sno∧SC.Cno='2'(Student×SC))

  1. 计算广义笛卡尔积

    • 在内存中尽可能多地装入某个表的若干块,留出一块存放另一个表的元组。

    • 把表2中的每个元组和表1中每个元组连接,连接后的元组装满一块后就写到中间文件上。

    • 从表2中读入一块和内存中的表1元组连接,直到表2处理完。

    • 重复上述处理过程,直到把表1处理完。

    • 设一个块能装10个表1元组或100个表2元组,在内存中存放5块表1元组和1块表2元组,则读取总块数为:

      1000/10 + 10000/(10×5)×10000/100 = 100 + 20×100 = 2100块

      其中:读表1 100块,读表2 20遍,每遍100块,则总计要读取2100数据块。

    • 连接后的元组数为10³×10⁴=10⁷。设每块能装10个元组,则写出10⁶块。

  2. 作选择操作

    • 依次读入连接后的元组,按照选择条件选取满足要求的记录,假定内存处理时间忽略。读取中间文件花费的时间(同写中间文件一样)需读入10⁶块。若满足条件的元组仅50个,均可放在内存。

  3. 作投影操作

    • 把第2步的结果在Sname上作投影输出,得到最终结果。

    • 第一种情况下执行查询的总读写数据块 = 2100 + 10⁶ + 10⁶。

第二种情况

Q2 = πSname(σSC.Cno='2'(Student ⋈ SC))

  1. 计算自然连接

    • 执行自然连接,读取表1和表2的策略不变,总的读取块数仍为2100块,自然连接的结果比第一种情况大大减少,为10⁴个元组,写出数据块 = 10³块。

  2. 读取中间文件块,执行选择运算

    • 读取的数据块 = 10³块。

  3. 把第2步结果投影输出

    • 第二种情况下执行查询的总读写数据块 = 2100 + 10³ + 10³,其执行代价大约是第一种情况的488分之一。

第三种情况

Q3 = πSname(Student ⋈ σSC.Cno='2'(SC))

  1. 先对表2作选择运算

    • 只需读一遍表2,存取100块,因为满足条件的元组仅50个,不必使用中间文件。

  2. 读取表1,把读入的表1元组和内存中的表2元组作连接

    • 也只需读一遍表1共100块。

  3. 把连接结果投影输出

    • 第三种情况总的读写数据块 = 100 + 100,其执行代价大约是第一种情况的万分之一,是第二种情况的20分之一。

分析

  • 假如表2的Cno字段上有索引,第一步就不必读取所有的表2元组而只需读取Cno='2'的元组(50个)。存取的索引块和表2中满足条件的数据块大约总共3~4块。

  • 若表1在Sno上也有索引,不必读所有的表1元组,因为满足条件的表2记录仅50个,涉及最多50个表1记录,读取表1的块数也可大大减少。

总结

  • 把代数表达式Q1变换为Q2、Q3:

    • Q1 = πSname(σStudent.Sno=SC.Sno∧SC.Cno='2'(Student×SC))

    • Q2 = πSname(σSC.Cno='2'(Student ⋈ SC))

    • Q3 = πSname(Student ⋈ σSC.Cno='2'(SC))

  • 有选择和连接操作时,先做选择操作,这样参加连接的元组就可以大大减少,这是代数优化。

  • 在Q3中,表2的选择操作算法有全表扫描或索引扫描,经过初步估算,索引扫描方法较优。

  • 对于表1和表2的连接,利用表1上的索引,采用索引连接代价也较小,这就是物理优化。


9.3 代数优化

9.3.1 关系代数表达式等价变换规则

代数优化策略是通过对关系代数表达式的等价变换来提高查询效率。关系代数表达式的等价是指用相同的关系代替两个表达式中相应的关系,所得到的结果是相同的,两个关系表达式E1和E2是等价的,可记为E1≡E2。

常用的等价变换规则:

  1. 连接、笛卡尔积交换律

    • 设E1和E2是关系代数表达式,F是连接运算的条件,则有:

      • E1 × E2 ≡ E2 × E1

      • E1 ⋈ E2 ≡ E2 ⋈ E1

      • E1 ⋈ E2 ≡ E2 ⋈ E1 F F

  2. 连接、笛卡尔积的结合律

    • 设E1,E2,E3是关系代数表达式,F1和F2是连接运算的条件:

      • (E1 × E2) × E3 ≡ E1 × (E2 × E3)

      • (E1 ⋈ E2) ⋈ E3 ≡ E1 ⋈ (E2 ⋈ E3)

      • (E1 ⋈ E2) ⋈ E3 ≡ E1 ⋈ (E2 ⋈ E3) F1 F2 F2 F1

  3. 投影的串接定律

    • πA1,A2,…,An(πB1,B2,…,Bm(E)) ≡ πA1,A2,…,An(E)

    • E是关系代数表达式,Ai(i=1,2,…,n),Bj(j=1,2,…,m)是属性名,{A1,A2,…,An}构成{B1,B2,…,Bm}的子集。

  4. 选择的串接定律

    • σF1(σF2(E)) ≡ σF1∧F2(E)

    • E是关系代数表达式,F1、F2是选择条件,选择的串接律说明选择条件可以合并,这样一次就可检查全部条件。

  5. 选择与投影操作的交换律

    • σF(πA1,A2,…,An(E)) ≡ πA1,A2,…,An(σF(E))

    • 选择条件F只涉及属性A1,A2,…,An,若F中有不属于A1,A2,…,An的属性B1,B2,…,Bm有更一般规则:

      • πA1,A2,…,An(σF(E)) ≡ πA1,A2,…,An(σF(πA1,A2,…,An,B1,B2,…,Bm(E)))

  6. 选择与笛卡尔积的交换律

    • 如果F中涉及的属性都是E1中的属性,则:

      • σF(E1×E2) ≡ σF(E1)×E2

    • 如果F=F1∧F2,且F1只涉及E1中的属性,F2只涉及E2中的属性,则由上面的等价变换规则1,4,6可推出:

      • σF(E1×E2) ≡ σF1(E1)×σF2(E2)

    • 若F1只涉及E1中的属性,F2涉及E1和E2两者的属性,则仍有:

      • σF(E1×E2) ≡ σF2(σF1(E1)×E2)

    • 它使部分选择在笛卡尔积前先做。

  7. 选择与并的分配律

    • 设E=E1∪E2,E1,E2有相同的属性名,则:

      • σF(E1∪E2) ≡ σF(E1)∪σF(E2)

  8. 选择与差运算的分配律

    • 若E1,E2有相同的属性名,则:

      • σF(E1-E2) ≡ σF(E1)-σF(E2)

  9. 选择对自然连接的分配律

    • σF(E1 ⋈ E2) ≡ σF(E1)⋈σF(E2)

  10. 投影与笛卡尔积的分配律

    • 设E1和E2是两个关系表达式,A1,A2,…,An是E1的属性,B1,B2,…,Bm是E2的属性,则:

      • πA1,A2,…,An,B1,B2,…,Bm(E1×E2) ≡ πA1,A2,…,An (E1)×πB1,B2,…,Bm(E2)

  11. 投影与并的分配律

    • 设E1和E2有相同的属性名,则:

      • πA1,A2,…,An(E1∪E2) ≡ πA1,A2,…,An(E1)∪πA1,A2,…,An(E2)

9.3.2 查询树的启发式优化

典型的启发式规则:

  1. 选择运算应尽可能先做:在优化策略中这是最重要、最基本的一条。

  2. 把投影运算和选择运算同时进行:如有若干投影和选择运算,且它们都对同一个关系操作,则可以在扫描此关系的同时完成所有的这些运算以避免重复扫描关系。

  3. 把投影同其前或其后的双目运算结合起来:没有必要为了去掉某些字段而扫描一遍关系。

  4. **把某些选择同在它前面要执行的笛卡尔积结合起来成为

第10章 数据库恢复技术

10.1 事务的基本概念

  • 事务的定义:事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位,是恢复和并发控制的基本单位。

  • 事务与程序的区别

    1. 在关系数据库中,一个事务可以是一条SQL语句、一组SQL语句或整个程序。

    2. 一个程序通常包含多个事务。

  • 事务的定义方式

    1. 显式定义方式

      • 正常结束格式:

        BEGIN TRANSACTION;
        SQL语句;
        COMMIT;

        提交事务的所有操作,将事务中的更新写回到磁盘上的物理数据库中。

      • 异常终止格式:

        BEGIN TRANSACTION;
        SQL语句;
        ROLLBACK;

        撤销事务中对数据库的所有已完成操作,事务回滚到开始时的状态。

  • 事务的特性(ACID特性)

    1. 原子性(Atomicity):事务中包括的所有操作要么都做,要么都不做。

    2. 一致性(Consistency):事务执行的结果必须使数据库从一个一致性状态变到另一个一致性状态。一致性状态是指数据库中只包含成功事务提交的结果;不一致状态是指数据库系统运行中发生故障,有些事务尚未完成就被迫中断,未完成事务对数据库的修改有一部分已写入物理数据库,此时数据库处于不正确的状态。

      • 举例:银行转账事务,从账号A中取出一万元,存入账号B。这两个操作要么全做,要么全不做,全做或全不做时数据库都处于一致性状态;如果只做操作①,用户逻辑上会发生错误,少了一万元,数据库就处于不一致性状态。

    3. 隔离性(Isolation):一个事务的执行不能被其他事务干扰,一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能互相干扰。

    4. 持续性(Durability):一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其执行结果有任何影响。

  • 破坏事务ACID特性的因素

    1. 多个事务并行运行时,不同事务的操作交叉执行。数据库管理系统必须保证多个事务的交叉运行不影响这些事务的隔离性。

    2. 事务在运行过程中被强行停止。数据库管理系统必须保证被强行终止的事务对数据库和其他事务没有任何影响。

10.2 数据库恢复概述

  • 故障的不可避免性:故障主要包括计算机硬件故障、软件错误、操作员失误、恶意破坏等。

  • 故障对数据库的影响:运行事务非正常中断、影响数据库中数据的正确性、数据库全部或部分丢失数据等。

  • 数据库恢复的作用:把数据库从错误状态恢复到某一已知的正确状态(亦称为一致状态或完整状态)。

  • 数据库恢复子系统的重要性:数据库恢复子系统是数据库管理系统的一个重要组成部分,代码占整个系统的10%。恢复技术是衡量系统优劣的重要指标,对系统的可靠程度起到决定性作用。

10.3 故障的种类

  • 事务内部的故障

    1. 事务内部的故障有的是可以通过事务程序本身发现的,有的是非预期的,不能由事务程序处理的。

    2. 举例:银行转账事务,当账户甲余额不足时,应用程序可以发现并让事务回滚,撤销已作的修改,恢复数据库到正确状态。事务内部更多的故障是非预期的,如运算溢出、死锁等。

    3. 事务故障的恢复:事务故障意味着事务没有达到预期的终点,数据库可能处于不正确状态。撤销该事务已经作出的任何对数据库的修改,使得该事务好像根本没有启动一样,这类恢复操作称为事务撤消(UNDO)。

  • 系统故障

    1. 系统故障称为软故障,是指造成系统停止运转的任何事件,使得系统要重新启动。

    2. 故障表现:整个系统的正常运行突然被破坏,内存中数据库缓冲区的信息全部丢失,所有正在运行的事务都非正常终止,不破坏数据库。

    3. 常见原因:特定类型的硬件错误(如CPU故障)、操作系统故障、数据库管理系统代码错误、系统断电等。

    4. 恢复策略

      • 表现一:发生系统故障时,一些尚未完成的事务的结果可能已送入物理数据库,造成数据库可能处于不正确状态。恢复策略是让所有非正常终止的事务回滚,强行撤消(UNDO)所有未完成事务。

      • 表现二:发生系统故障时,有些已完成的事务可能有一部分甚至全部留在缓冲区,尚未写回到磁盘上的物理数据库中,系统故障使得这些事务对数据库的修改部分或全部丢失。恢复策略是重做(REDO)所有已提交的事务。

  • 介质故障

    1. 介质故障称为硬故障,指外存故障,如磁盘损坏、磁头碰撞、瞬时强磁场干扰等。

    2. 故障表现:破坏数据库或部分数据库,并影响正在存取这部分数据的所有事务。

    3. 介质故障比前两类故障的可能性小得多,但破坏性大得多。

  • 计算机病毒

    1. 计算机病毒是一种可繁殖、传播并对计算机造成破坏的计算机程序。

    2. 计算机病毒的特点:隐蔽性、潜伏性、传染性、破坏性、寄生性。

    3. 数据库一旦被病毒破坏仍要用恢复技术把数据库加以恢复。

  • 小结

    1. 各类故障对数据库的影响主要有数据库本身被破坏和数据库没有被破坏,但数据不正确。

    2. 恢复操作的基本原理是冗余,恢复的实现技术较复杂,一个大型数据库产品,恢复子系统的代码要占全部代码的10%以上。

10.4 恢复的实现技术

  • 恢复机制的关键问题:如何建立冗余数据、如何利用这些冗余数据实施数据库恢复。

  • 建立数据冗余的方法

    1. 数据转储(backup)

      • 定义:数据转储是指数据库管理员定期地将整个数据库复制到磁带、磁盘或其他存储介质上保存起来的过程。这些备用的数据文本称为后备副本(backup)或后援副本。

      • 说明:后备副本只将数据库恢复到转储时的状态,要想恢复到故障发生时的状态,必须重新运行自转储以后的所有更新事务。

      • 转储方法

        • 静态转储:在系统中无运行事务时进行的转储操作,即转储期间不允许对数据库进行任何存取、修改活动。优点是实现简单;缺点是降低了数据库的可用性,因为转储必须等待正运行的用户事务结束,新的事务必须等转储结束。

        • 动态转储:转储操作与用户事务并发进行,转储期间允许对数据库进行存取或修改。优点是不用等待正在运行的用户事务结束,不会影响新事务的运行;缺点是不能保证副本中的数据正确有效。利用动态转储得到的副本进行故障恢复,需要把动态转储期间各事务对数据库的修改活动登记下来,建立日志文件。后备副本加上日志文件就能把数据库恢复到某一时刻的正确状态。

      • 海量转储与增量转储

        • 海量转储:每次转储全部数据库。

        • 增量转储:只转储上次转储后更新过的数据。

        • 比较:从恢复角度看,使用海量转储得到的后备副本进行恢复往往更方便。如果数据库很大,事务处理又十分频繁,则增量转储方式更实用更有效。

      • 数据转储分类

        • 转储方式:动态转储、静态转储

        • 转储状态:海量转储(动态海量转储、静态海量转储)、增量转储(动态增量转储、静态增量转储)

    2. 登记日志文件(logging)

      • 日志文件的格式和内容

        • 日志文件是用来记录事务对数据库的更新操作的文件。

        • 日志文件的格式

          • 以记录为单位的日志文件和以数据块为单位的日志文件两种。

          • 以记录为单位的日志文件需要登记的内容:

            • 各个事务的开始标记(BEGIN TRANSACTION);

            • 各个事务的结束标记(COMMIT或ROLLBACK);

            • 各个事务的所有更新操作。

            • 以上均作为日志文件中的一个日志记录(log record)。

            • 每条日志记录(log record)的内容:

              • 事务标识(标明是哪个事务)。

              • 操作类型(插入、删除或修改)。

              • 操作对象(记录内部标识)。

              • 更新前数据的旧值(对插入操作而言,此项为空值)。

              • 更新后数据的新值(对删除操作而言,此项为空值)。

          • 以数据块为单位的日志文件,每条日志记录的内容:

            • 事务标识、被更新的数据块。

      • 日志文件的作用

        • 用于事务故障恢复和系统故障恢复,并协助后备副本进行介质故障恢复。

        • 在动态转储方式中必须建立日志文件,后备副本和日志文件结合起来才能有效地恢复数据库。

        • 在静态转储方式中,也可以建立日志文件。利用日志文件,把已完成的事务进行重做处理,对故障发生时尚未完成的事务进行撤销处理。

      • 登记日志文件

        • 为保证数据库是可恢复的,登记日志文件时必须遵循两条原则:

          • 登记的次序严格按并发事务执行的时间次序。

          • 必须先写日志文件,后写数据库。

10.5 恢复策略

  • 事务故障的恢复

    1. 事务故障:事务在运行至正常终止点前被终止,恢复子系统利用日志文件撤消(UNDO)此事务已对数据库进行的修改。

    2. 恢复步骤

      • 反向扫描文件日志(即从最后向前扫描日志文件),查找该事务的更新操作。

      • 对该事务的更新操作执行逆操作。即将日志记录中“更新前的值”写入数据库。插入操作,“更新前的值”为空,则相当于做删除操作;删除操作,“更新后的值”为空,则相当于做插入操作;修改操作,则相当于用修改前值代替修改后值。

      • 继续反向扫描日志文件,查找该事务的其他更新操作,并做同样处理。

      • 如此处理下去,直至读到此事务的开始标记,事务故障恢复就完成了。

  • 系统故障的恢复

    1. 系统故障造成数据库不一致状态的原因有两个:一是未完成事务对数据库的更新可能已写入数据库,二是已提交事务对数据库的更新可能还留在缓冲区没来得及写入数据库。

    2. 恢复方法

      • UNDO故障发生时未完成的事务。

      • REDO已完成的事务。

    3. 恢复步骤

      • 正向扫描日志文件(即从头扫描日志文件),找出在故障发生前已经提交的事务,加入重做队列,找出故障发生时尚未完成的事务,加入撤销队列。

      • 对撤销队列事务进行撤销处理。反向扫描日志文件,对每个撤销事务的更新操作执行逆操作,即将日志记录中“更新前的值”写入数据库。

      • 对重做队列事务进行重做处理。正向扫描日志文件,对每个重做事务重新执行登记的操作,即将日志记录中“更新后的值”写入数据库。

    4. 说明:系统故障的恢复由系统在重新启动时自动完成,不需要用户干预。

  • 介质故障的恢复

    1. 介质故障后磁盘上的物理数据和日志文件被破坏,这是最严重的一种故障,恢复方法是重装数据库,然后重做已完成的事务。

    2. 恢复步骤

      • 装入最新的后备数据库副本(离故障发生时刻最近的转储副本),使数据库恢复到最近一次转储时的一致性状态。对于静态转储的数据库副本,装入后数据库处于一致性状态;对于动态转储的数据库副本,还须同时装入转储时刻的日志文件副本,利用恢复系统故障的方法(即REDO+UNDO),才能将数据库恢复到一致性状态。

      • 装入有关的日志文件副本(转储结束时刻的日志文件副本),重做已完成的事务。首先扫描日志文件,找出故障发生时已提交的事务的标识,将其记入重做队列。然后正向扫描日志文件,对重做队列中的所有事务进行重做处理。即将日志记录中“更新后的值”写入数据库。

    3. 说明:介质故障的恢复需要数据库管理员介入,数据库管理员的工作是重装最近转储的数据库副本和有关的各日志文件副本,执行系统提供的恢复命令,具体的恢复操作仍由数据库管理系统完成。

10.6 具有检查点的恢复技术

  • 问题的提出

    1. 利用日志技术进行数据库恢复时,恢复子系统必须搜索日志,确定哪些事务需要重做,哪些事务需要撤销。但存在两个问题:一是搜索整个日志将耗费大量的时间,二是重做处理,重新执行,浪费了大量时间。

    2. 解决方案:具有检查点(checkpoint)的恢复技术,即在日志文件中增加检查点记录,增加重新开始文件,恢复子系统在登录日志文件期间动态地维护日志。

  • 检查点技术

    1. 检查点记录的内容

      • 建立检查点时刻所有正在执行的事务清单。

      • 这些事务最近一个日志记录的地址。

      • 重新开始文件的内容。

      • 记录各个检查点记录在日志文件中的地址。

    2. 动态维护日志文件的方法

      • 周期性地执行如下操作:建立检查点,保存数据库状态。

      • 具体步骤是:

        • 将当前日志缓冲区中的所有日志记录写入磁盘的日志文件上。

        • 在日志文件中写入一个检查点记录。

        • 将当前数据缓冲区的所有数据记录写入磁盘的数据库中。

        • 把检查点记录在日志文件中的地址写入一个重新开始文件。

    3. 说明:恢复子系统可以定期或不定期地建立检查点,保存数据库状态,即按照预定的一个时间间隔,如每隔一小时建立一个检查点,或者按照某种规则,如日志文件已写满一半建立一个检查点。

  • 利用检查点的恢复策略

    1. 使用检查点方法可以改善恢复效率:当事务T在一个检查点之前提交,T对数据库所做的修改已写入数据库;写入时间是在这个检查点建立之前或在这个检查点建立之时,这样在进行恢复处理时,没有必要对事务T执行重做操作。

    2. 系统出现故障时,恢复子系统将根据事务的不同状态采取不同的恢复策略:

      • T1:在检查点之前提交。

      • T2:在检查点之前开始执行,在检查点之后故障点之前提交。

      • T3:在检查点之前开始执行,在故障点时还未完成。

      • T4:在检查点之后开始执行,在故障点之前提交。

      • T5:在检查点之后开始执行,在故障点时还未完成。

      • T3和T5在故障发生时还未完成,所以予以撤销。

      • T2和T4在检查点之后才提交,它们对数据库所做的修改在故障发生时可能还在缓冲区中,尚未写入数据库,所以要重做。

      • T1在检查点之前已提交,所以不必执行重做操作。

    3. 利用检查点的恢复步骤

      • 从重新开始文件中找到最后一个检查点记录在日志文件中的地址,由该地址在日志文件中找到最后一个检查点记录。

      • 由该检查点记录得到检查点建立时刻所有正在执行的事务清单ACTIVE-LIST。建立两个事务队列UNDO-LIST和REDO-LIST。把ACTIVE-LIST暂时放入UNDO-LIST队列,REDO队列暂为空。

      • 从检查点开始正向扫描日志文件,直到日志文件结束。如有新开始的事务Ti,把Ti暂时放入UNDO-LIST队列,如有提交的事务Tj,把Tj从UNDO-LIST队列移到REDO-LIST队列;直到日志文件结束。

      • 对UNDO-LIST中的每个事务执行UNDO操作,对REDO-LIST中的每个事务执行REDO操作。

10.7 数据库镜像

  • 背景:介质故障是对系统影响最为严重的一种故障,严重影响数据库的可用性,因为当出现介质故障时全部应用中断,恢复比较费时。为预防介质故障,数据库管理员必须周期性地转储数据库。

  • 数据库镜像的定义:数据库镜像是指数据库管理系统自动把整个数据库或其中的关键数据复制到另一个磁盘上,每当主数据库更新时,数据库管理系统自动把更新后的数据复制过去,保证镜像数据与主数据的一致性。

  • 数据库镜像的作用

    1. 出现介质故障时可由镜像磁盘继续提供使用,同时数据库管理系统自动利用镜像磁盘数据进行数据库的恢复,不需要关闭系统和重装数据库副本。

    2. 没有故障时可用于并发操作,一个用户对数据加排他锁修改数据,其他用户可读镜像数据库上的数据,不必等待该用户释放锁。

10.8 小结

  • 事务的概念和性质:事务是数据库的逻辑工作单位,是恢复的基本单位,也是并发控制的基本单位。要保证事务的原子性、一致性、隔离性和持续性。

  • 故障的种类:事务故障、系统故障、介质故障。

  • 恢复中最经常使用的技术:数据库转储、登记日志文件。

  • 恢复的基本原理:利用存储在后备副本、日志文件和数据库镜像中的冗余数据来重建数据库。

第11章 并发控制

11.1 并发控制概述

  • 多用户数据库系统:允许多个用户同时使用的数据库系统,特点是在同一时刻并发运行的事务数可达数百上千个,涉及并行控制。例如飞机定票数据库系统、银行数据库系统等。

  • 事务执行方式

    1. 事务串行执行:每个时刻只有一个事务运行,其他事务必须等待当前事务结束,不能充分利用系统资源。

    2. 交叉并发方式:在单处理机系统中,事务的并行操作轮流交叉运行,减少处理机空闲时间,提高效率。

    3. 同时并发方式:多处理机系统中,多个处理机同时运行多个事务,实现真正的并行运行。

  • 并发控制机制的任务

    1. 对并发操作进行正确调度。

    2. 保证事务的隔离性。

    3. 保证数据库的一致性。

  • 并发操作带来的数据不一致性实例

    • 丢失修改:两个事务读入同一数据并修改,后提交的事务破坏了先提交事务的结果,导致先提交事务的修改丢失。

    • 不可重复读:事务T1读取数据后,事务T2更新数据,导致T1无法再现前一次读取结果。包括三种情况:修改数据、删除数据、插入数据。

    • 读“脏”数据:事务T1修改数据后写回磁盘,事务T2读取该数据后,T1因某种原因被撤销,其修改作废,T2读到的数据与数据库内容不一致。

11.2 封锁

  • 定义:事务T在对某个数据对象操作之前,先向系统发出请求,对其加锁。加锁后事务T对该数据对象有控制权,在事务T释放锁之前,其他事务不能更新此数据对象。

  • 基本封锁类型

    • 排它锁(X锁):写锁,事务T对数据对象A加X锁后,其他事务不能对A加任何类型的锁,直到T释放A上的锁。

    • 共享锁(S锁):读锁,事务T对数据对象A加S锁后,其他事务只能对A加S锁,不能加X锁,直到T释放A上的S锁。

  • 锁的相容矩阵

    • T2 \ T1XS_
      XNNY
      SNYY
      _YYY

11.3 封锁协议

  • 定义:在运用X锁和S锁对数据对象加锁时,需要约定一些规则,这些规则为封锁协议。

  • 三级封锁协议

    1. 一级封锁协议

      • 事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。

      • 作用:防止丢失修改,保证事务可恢复。

    2. 二级封锁协议

      • 一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。

      • 作用:防止丢失修改和读“脏”数据。

    3. 三级封锁协议

      • 一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。

      • 作用:防止丢失修改、读“脏”数据和不可重复读。

11.4 活锁和死锁

  • 活锁

    • 定义:事务T1封锁了数据R,事务T2请求封锁R,T2等待。T3也请求封锁R,当T1释放R上的封锁后,系统批准了T3的请求,T2继续等待。T2可能永远等待,导致活锁。

    • 避免方法:采用先来先服务的策略,按请求封锁的先后次序对事务排队。

  • 死锁

    • 定义:事务T1封锁了数据R1,事务T2封锁了数据R2。T1请求封锁R2,T2请求封锁R1,导致T1和T2互相等待,形成死锁。

    • 解决方法:

      1. 死锁的预防

        • 一次封锁法:要求事务一次将所有要使用的数据全部加锁,否则不能继续执行。缺点是降低系统并发度,且难以事先确定封锁对象。

        • 顺序封锁法:预先对数据对象规定一个封锁顺序,所有事务按此顺序封锁。缺点是维护成本高,且难以实现。

      2. 死锁的诊断与解除

        • 超时法:如果事务的等待时间超过规定时限,则认为发生死锁。优点是实现简单,缺点是可能误判,且时限设置过长会导致死锁不能及时发现。

        • 等待图法:用事务等待图动态反映所有事务的等待情况。如果等待图中存在回路,则表示系统中出现了死锁。解除方法是选择一个处理死锁代价最小的事务,将其撤销,释放其持有的所有锁。

11.5 并发调度的可串行性

  • 可串行化调度:多个事务并发执行的结果与按某一次序串行地执行这些事务时的结果相同。可串行性是并发事务正确调度的准则。

  • 冲突可串行化调度

    • 定义:冲突操作是指不同事务对同一数据的读写操作和写写操作。如果一个调度在保证冲突操作次序不变的情况下,通过交换两个事务不冲突操作的次序得到另一个串行调度,则该调度是冲突可串行化的。

    • 性质:冲突可串行化调度一定是可串行化调度,但不是必要条件。

11.6 两段锁协议

  • 定义:所有事务必须分两个阶段对数据项加锁和解锁。第一阶段是获得封锁(扩展阶段),事务可以申请获得任何数据项上的任何类型的锁,但不能释放任何锁。第二阶段是释放封锁(收缩阶段),事务可以释放任何数据项上的任何类型的锁,但不能再申请任何锁。

  • 性质

    • 事务遵守两段锁协议是可串行化调度的充分条件,但不是必要条件。

    • 若并发事务都遵守两段锁协议,则任何并发调度策略都是可串行化的。

    • 一次封锁法遵守两段锁协议,但遵守两段锁协议的事务可能发生死锁。

11.7 封锁的粒度

  • 定义:封锁对象的大小称为封锁粒度。封锁对象可以是逻辑单元(如属性值、元组、关系等)或物理单元(如页、物理记录等)。

  • 封锁粒度与系统性能的关系

    • 封锁粒度越大,并发度越小,系统开销越小。

    • 封锁粒度越小,并发度越高,系统开销越大。

  • 多粒度封锁

    • 定义:在一个系统中同时支持多种封锁粒度供不同事务选择。

    • 选择原则:根据事务处理的数据量选择封锁粒度。处理大量元组的事务以关系为封锁单元,处理少量元组的事务以元组为封锁单元。

    • 多粒度树:以树形结构表示多级封锁粒度,根结点是整个数据库,叶结点是最小的数据粒度。

    • 多粒度封锁协议:允许多粒度树中的每个结点被独立地加锁,对一个结点加锁意味着其所有后裔结点也被加以同样类型的锁。

  • 意向锁

    • 目的:提高对某个数据对象加锁时系统的检查效率。

    • 常用意向锁

      • IS锁(Intent Share Lock):表示后裔结点拟加S锁。

      • IX锁(Intent Exclusive Lock):表示后裔结点拟加X锁。

      • SIX锁(Share Intent Exclusive Lock):表示对数据对象加S锁,同时拟对其后裔结点加X锁。

    • 意向锁的相容矩阵

      • T2 \ T1XSISIXSIX
        XNNNNN
        SNYYNN
        ISNYYYN
        IXNNYYN
        SIXNNNNN

11.8 其他并发控制机制

  • 时间戳方法

    • 给每个事务盖上一个时标(事务开始执行的时间),各事务按照时间戳解决冲突。如冲突则回滚具有较早时间戳的事务,回滚的事务赋予新的时间戳并从头开始执行。

  • 乐观控制法

    • 认为事务执行时间很少发生冲突,不对事务进行特殊管制,事务提交前再进行准确性检查。如果检查后发现冲突并影响可串行性,则拒绝提交并回滚该事务。

  • 多版本并发控制(MVCC)

    • 定义:通过维护数据库对象的多个版本信息来实现高效并发控制。

    • 版本的定义:数据对象的一个快照,记录了数据对象某个时刻的状态。

    • 多版本并发控制协议

      • 每个write(Q)创建一个新版本Qm,形成版本序列Q1, Q2, ..., Qm。

      • 每个版本Qk包括版本值、创建Qk事务的时间戳W-timestamp(Qk)和成功读取Qk事务的最大时间戳R-timestamp(Qk)。

      • 若事务T发出Read(Q),返回小于或等于TS(T)的最大时间戳的版本内容。

      • 若事务T发出Write(Q),判断是否回滚或覆盖版本。

      • 删除旧版本:若两个版本的W-timestamp都小于系统中最老的时间戳,则删除旧版本。

    • 改进的多版本并发控制

      • 将事务分为只读事务和更新事务。

      • 只读事务采用多版本时间戳,更新事务采用两阶段封锁(2PL)协议。

      • 引入验证锁(C锁),提高系统并发性。

11.9 小结

  • 数据库的并发控制以事务为单位,通常使用封锁机制,最常用的是三级封锁协议。

  • 并发控制机制调度事务正确性的判断准则是可串行性,通常由两段锁协议来保证。

  • 其他并发控制机制包括时间戳方法、乐观控制法和多版本并发控制。

第12章 数据库管理系统

12.1 数据库管理系统的基本功能

  1. 数据库定义和创建

    • 创建数据库主要用数据语言定义和创建数据库模式、外模式、内模式等数据库对象,并存储在数据字典中,是数据库管理系统运行的基本依据。

    • 示例:创新数据库、表、视图、索引等,创建用户、安全保密定义、数据库完整性定义。

  2. 数据组织、存储和管理

    • 数据库管理系统分类组织、存储和管理各种数据字典、用户数据、存取路径等。

    • 目标是提高存储空间利用率和方便存取,提供多种存取方法以提高存取效率。

    • 任务是以某种文件结构和存取方式在存储器上组织这些数据,实现数据之间的联系。

  3. 数据存取

    • 数据库系统提供用户对数据的操作功能,实现对数据库数据的检索、插入、修改和删除。

    • 两类数据库操作语言:宿主型语言和自立(独立)型语言。

  4. 数据库事务管理和运行管理

    • 对多用户环境下事务管理功能和安全性、完整性控制功能;包括数据库恢复、并发控制和死锁检测、安全性检查和存取控制、完整性检查和执行、运行日志的组织管理等保证数据库系统的正常运行和事务的ACID特性。

  5. 数据库的建立和维护

    • 数据库的初始建立、数据的转换、数据库的转储和恢复、数据库的重组织和重构造以及性能监测分析等。

  6. 其他功能

    • 数据库管理系统与网络中软件系统的通信功能,数据库系统之间、数据库与文件系统的数据转换,异构数据库之间的互访和互操作。

12.2 数据库管理系统的系统结构

12.2.1 数据库管理系统的层次结构

  • 将数据库管理系统划分为若干层次,有利于清楚的认识数据库管理系统,同时有助于数据库管理系统的设计和维护。

  • 示例:IBM最早研制的SystemR,其核心分为底层的关系存储系统(RSS)和上层的关系数据库系统(RDS)。

    • RSS:空间和设备管理、索引和存取路径管理、事务管理、并发控制、运行日志管理和恢复等。

    • RDS:语法检查和分析、优化、代码生成、视图实现、安全性完整性检查等。

  • 关系数据库管理系统的层次结构

    • 数据存储层:处理数据页和系统缓冲区。

    • 数据存取层:处理单个元组把集合操作化为单记录操作并执行。

    • 语言翻译处理层:处理数据库语言,如SQL向上提供的数据接口是元组的集合。

    • 应用层:处理各种各样的数据库应用是RDBMS与用户/应用程序的界面层。

12.2.2 关系数据库管理系统的运行过程示例

  • 关系数据库管理系统是一个复杂而有序的整体,应该用动态的观点看待关系数据库管理系统的各个功能模块。

  • 示例:应用程序/用户通过关系数据库管理系统读取数据库中数据的过程。具体如下:

    1. 用户A通过应用程序A向RDBMS发出调用数据库数据的命令,如SELECT,给出一个关系名和查找条件。

    2. RDBMS通过数据字典对命令进行语法检查,通过后进行语义检查和存取权限的检查。

    3. RDBMS进行查询优化,并转换成一串记录的存取操作系列。

    4. RDBMS执行存取操作序列(反复执行以下各步,直至结束)。

    5. RDBMS首先在系统缓冲区中查找记录,若找到满足条件的记录则转到第10步,否则转到第6步。

    6. RDBMS查看存储模式,决定从哪个文件,用什么方式读取哪个物流记录。

    7. RDBMS根据6的结果向操作系统发出读取记录的命令。

    8. 操作系统执行读取数据的有关操作。

    9. 操作系统将数据从数据库的存储区送至系统缓冲区。

    10. RDBMS根据查询命令和数据字典的内容导出用户所要读取的记录格式。

    11. RDBMS将数据记录从系统缓冲区传送到应用程序A的用户工作区。

    12. RDBMS将执行状态信息,如成功读取或不成功的错误提示等返回给应用程序A。

  • 结合RDBMS的层次结构,以上12个动作可大致分为以下的对应关系:

    • 动作1属于第一层——应用层。

    • 动作2、3属于第二层——语言处理层。

    • 动作4、10、11、12属于第三层——数据存取层。

    • 动作5、6、7属于第四层——数据存储层。

    • 动作8、9由操作系统完成。

12.3 语言处理层

12.3.1 语言处理层的任务和工作步骤

  • 语言处理层任务:把用户在各种方式下提交给RDBMS的数据库语句转换成对RDBMS内层可执行的基本存取模块的调用序列。

    • 数据库语言包括数据定义语言、数据操作语言和数据控制语言。其中数据定义语言的处理相对独立和简单。

    • 数据字典是数据操作语言处理、执行以及RDBMS运行管理的基本依据。数据字典通常应用关系表来表示。

    • 对数据操作语言,语言处理层做的工作较多,具体如下:

      1. 针对数据操作语言进行词法分析和语法分析,把外部关系名、属性名转换为内部名。

      2. 根据数据字典中的内容进行查询检查,包括审核用户的存取权限和完整性检查。

      3. 对查询进行优化,包括代数优化,存取路径优化。

  • 总之,将数据库操纵语句转换成一串可执行的存取动作,这个过程称为一个逐步束缚的过程。根据束缚时间可分为:解释方法即在执行时束缚,预编译方法即在执行前束缚。

12.3.2 解释方法

  • 解释方法的做法:在执行前,数据操纵语句都以原始字符串的形式保存;当执行到该语句的时候,解释程序完成束缚过程,然后予以执行。目前主要用在交互式SQL语言中。

    • 优点:数据独立性好、灵活、应变性好。

    • 缺点:效率比较低。

12.3.3 预编译方法

  • 预编译方法的基本思想:用户提交数据操纵语句之后,在运行之前对它进行翻译处理,保存产生好的可执行代码;当需要运行时,取出保存的可执行代码加以执行。

  • 以DB2数据库处理嵌入SQL语句的应用程序的过程为例,具体处理过程如下:

    1. 源程序P经过预编译器处理,识别SQL语句,生成数据库请求模块DBRM。

    2. 源程序按照通用方式被编译、链接处理,生成装载模块。

    3. 束缚依据数据字典和存取模块,生成应用规划。应用规划包括了对基本存取模块的调用,完成对应SQL语句的功能。

    4. 在运行时当装载模块遇到访问数据库时,就把控制权交给运行监督器。

    5. 运行监督器找到其应用规划,并调入内存并转让控制权。

    6. 应用规划启动数据存储器存取实际数据,将结果返回应用程序。

  • 存在的问题:应用规划失效,即会出现在束缚过程中进行优化所依据的条件可能在运行前就不存在了,例如数据库结构改变、存取路径改变。

  • 解决方法:

    • 重编译方法即当数据库中因某些成分的改变而使一些程序的编译结果无效时,再进行一次编译。

    • 重编译不应该在数据库刚改变就立即执行;较好的方法是将受影响的编译结果设置为“无效”,当被执行时才进行自动重编译。

    • 自动重编译技术的优点:既拥有了编译时进行束缚所带来的高效率,又具备了执行时束缚带来的数据独立性。

12.4 数据存取层

12.4.1 数据存取层的系统结构

  • 数据存取层介于语言处理层和数据存储层。向上提供单元组接口,即导航式的一次一个元组的存取操作;向下则以系统缓冲区的存储器接口作为实现基础。

  • 数据存取层的主要任务为:

    1. 提供一次一个元组的查找、插入、删除、修改等操作。

    2. 提供元组查找所循存取路径以及对存取路径的维护操作,如对索引记录的查找、插入、删除、修改。若索引是采用B+树,则应提供B+树的建立、查找、插入、删除、修改等功能。

    3. 对记录和存取路径的封锁、解锁操作。

    4. 日志文件的登记和读取操作。

    5. 其他辅助操作,如扫描、排序/合并等。

12.4.2 数据存取层的功能子系统

一、记录存取、事务管理子系统
  1. 记录存取子系统

    • 提供按照某个属性值直接取一个元组和顺序取一个元组的存取原语。如下列操作:

      • 在某个存取路径上按属性值找元组(FIND);

      • 按相对位置找元组(NEXT,PRIOR,FIRST,LAST);

      • 给某关系增加一个元组(INSERT);

      • 从找到的元组中取某个属性值(GET);

      • 从某关系中删去一个元组(DELETE);

      • 把某修改完的元组写回关系中(REPLACE)。

  2. 事务管理子系统

    • 提供定义和控制事务的操作。如下列操作:

      • 定义事务开始(BEGIN TRANSACTION);

      • 事务提交(COMMIT);

      • 事务回滚(ROLLBACK)。

二、日志登记子系统
  • 日志登记子系统和事务管理子系统紧密配合,完成关系数据库管理系统对事务和数据库的恢复任务。相关的操作有:

    • 写日志记录(WRITELOG);

    • 读日志记录(READLOG);

    • 扫描日志文件(SCANLOG);

    • 撤销尚未结束的事务(UNDO);

    • 重做已经结束的事务(REDO)。

三、控制信息管理模块
  • 利用专门的数据区登记不同记录类型及不同存取路径的说明信息和控制信息,为存取元组和管理事务提供依据。

四、排序/合并子系统
  • 该系统完成关系元组的重新排序,以满足用户的有序输出或加速关系运算的中间步骤。主要用途如下:

    1. 输出有序结果

      • 示例:SELECT Eno,Salary FROM EMP ORDER BY Salary DESC; 若EMP表上的Salary没有索引,则必须按照Salary的属性值降序排序。

    2. 数据预处理

      • 对于并、交、差、分组聚集、连接、取消重复值、属于、不属于等关系运算,当参与运算的关系无法全部放入内存时,先对其进行排序处理,再在有序表上执行相应操作,这样可以提高效率。

    3. 支持动态建立索引结构

      • 在B+树建立索引结构的时候需要对元组标识符(TID)进行排序。

    4. 减少数据块的存取次数

      • 利用B+树索引存取元组时,首先对TID排序,使相同的或相邻的聚集在一起,然后按数据块号顺序存取物理数据块,避免无序状态下重复读块的情况,减少数据块的存取次数。

五、存取路径维护子系统
  • 对数据执行插入、删除、修改操作的同时对相应的存取路径进行维护。

    • 示例:用B+树索引作为存取路径,则对元组进行插入、删除、修改操作时要在该表上已建立的所有B+树索引进行动态维护。

六、封锁子系统
  • 完成并发控制功能。

    1. 数据库系统的封锁与操作系统的封锁对比如下表(具体内容未在文件中给出)。

    2. 数据库系统中封锁子系统设计的难点不仅在于技术复杂还在于实现手段依赖操作系统提供的环境。

非常抱歉之前的回答中遗漏了部分内容。以下是文件中12.5 缓冲区管理和后续内容的完整提取:


12.5 缓冲区管理

数据存取层下面是数据存储层。该层的主要功能是存储管理,包括缓冲区管理、内外存交换、外存管理等。数据存储层向数据存取层提供的接口由定长页面组成的系统缓冲区。

1. 系统缓冲区设立的原因
  1. DBMS的设备独立性:外存设备变更不会对它们造成影响。

  2. 提高存取效率:预先读,延迟写。

2. 系统缓冲区的组成

由内存或虚存组成,缓冲区的大小、缓冲区内存和虚存部分的比例要精心设计,并动态调整,否则会出现“抖动”。缓冲区与上下接口的示意图如下:

3. 缓冲区内部管理操作

主要有查找页、申请页、淘汰页。调用操作系统的操作有读和写。以读为例,缓冲区的管理过程大致如下:

  • 说明

    1. 缓冲区管理主要算法是淘汰算法和查找算法。

    2. 常见的缓冲区淘汰算法有:

      • 先进先出算法(FIFO)

      • 最近最少使用的淘汰算法(LRU)

    3. 缓冲区查找算法:

      • 顺序查找算法

      • 折半查找算法

      • Hash查找算法


12.6 数据库物理组织

如何将庞大的数据集合以最优的形式组织起来存放到外存上是一个非常重要的问题。最优是指:存储效率高,节省存储空间;存取效率高,速度快,代价小。

数据库通过文件的方式存储数据库以下4类数据:

  1. 数据外模式、模式、内模式。

  2. 数据本身。

  3. 数据之间的联系。

  4. 存取路径。

1. 数据字典的组织

有关数据的描述存储在数据库的数据字典中。其特点是数据量比较小,使用频繁。

  • 数据字典的存储方式

    • 方式一:数据字典可以有多个表,在物理上可以将一个数据字典表对应一个物理文件,由操作系统负责存储管理。

    • 方式二:在物理上可以将若干数据字典表对应一个物理文件,由RDBMS系统负责存储管理。

2. 数据及数据联系的组织

数据库管理系统可根据数据和处理的要求自己设计文件结构,也可以从操作系统提供的文件结构中选择合适的加以实现。

  • 操作系统提供的文件格式有:

    • 顺序文件

    • 索引文件

    • 索引顺序文件

    • Hash文件

    • B树类文件等

  • 数据库物理组织中主要考虑和设计的是数据的组织和存储中必须直接和间接、显示或隐含体现数据之间的联系

    • 在关系数据库中因为数据和数据之间的联系用“表”表示,所以物理组织中可以用前面提到的数据字典的两种物理存储方法。

    • 在网状数据库中实现的方式是指引元,即增加数据库管理系统控制和维护的系统数据项——指引元,并与数据项在一个记录中。

3. 存取路径的组织
  • 网状、层次数据库存取路径是用数据之间的联系表示的,已与数据结合并固定下来。

  • 在关系数据库中存取路径和数据是分离的,对用户是隐蔽的,并动态建立和删除。通常采用B树类文件结构和Hash文件结构。


12.7 小结

  1. 主要介绍了数据库管理系统的基本功能、系统结构及主要的实现技术。

  2. 按照关系数据库管理系统的层次结构依次介绍了语言处理、数据存取、缓冲区管理、数据物理组织等各个层次的主要任务和功能。

第13章 数据库技术发展

13.1 数据库技术发展概述

  • 数据库技术产生于 20世纪60年代中期,以数据建模和 DBMS(数据库管理系统)核心技术 为主,发展成为一门内容丰富的学科,带动了巨大的软件产业。

  • 数据库技术是计算机科学技术中发展最快的领域之一,也是应用最广的技术之一。

  • 数据库系统的发展、特点和相互关系可以从 数据模型、新技术内容、应用领域 三个方面进行描述。

13.2 数据库发展的3个阶段

13.2.1 第一代数据库系统

  • 定义:第一代数据库系统指 层次和网状数据库系统,属于格式化模型。

  • 代表系统

    • IMS(Information Management System):1969年IBM公司研制的层次模型的数据库管理系统。

    • DBTG报告(Data Base Task Group):20世纪60年代末70年代初由美国数据库系统语言研究会(CODASYL)下属的数据库任务组提出,基于网状结构,是数据库网状模型的典型代表。

  • 共同特点

    • 支持 三级模式的体系结构

    • 使用 存取路径 表示数据之间的联系。

    • 具有独立的 数据定义语言(DDL)

    • 使用 导航的数据操纵语言,用户需要指出“怎么干”。

  • 优点:存取效率高。

  • 缺点:编程繁琐。

13.2.2 第二代数据库系统

  • 定义:第二代数据库系统指 支持关系数据模型的关系数据库系统

  • 理论基础:1970年,E.F.Codd发表《大型共享数据库数据的关系模型》论文,奠定了关系数据库技术的理论基础。

  • 典型代表

    • IBM San Jose研究室开发的 System R

    • Berkeley大学研制的 INGRES

  • 特点

    • 模型简单清晰。

    • 理论基础好。

    • 数据库语言 非过程化

    • 数据独立性强和 标准化

  • 主要成果

    • 奠定关系模型的理论基础。

    • 研究关系数据语言(如关系代数、关系演算、SQL及QBE等),确定SQL为关系数据库语言标准。

    • 攻克查询优化、并发控制、故障恢复等关键技术。

13.2.3 新一代数据库系统

  • 范围广泛

    • 基于 对象关系(OR)数据模型,采用分布式、客户机-服务器体系结构。

    • 混合式体系结构,在 对称多处理结构(SMP)、大规模并行处理(MPP)并行机 上运行的并行数据库。

    • 应用于特定领域的数据库,如工程数据库、统计数据库、空间数据库等。

  • 第三代数据库系统特征(1990年高级DBMS功能委员会提出):

    • 支持 数据管理、对象管理和知识管理

    • 保持或继承第二代数据库系统的技术。

    • 对其他系统开放。

13.3 数据库系统发展的特点

13.3.1 数据模型的发展

  • 关系模型:关系模型的提出是数据库发展史上的重大事件,其成功促进了关系数据库的发展,成为统治地位的数据模型。

  • 新数据模型的提出

    • 面向对象数据模型(OO模型)

      • 结合语义数据模型和面向对象程序设计方法。

      • 基本概念包括对象、类、继承等。

      • 主要产品有 Object Store、O2、ONTOS 等。

      • 对象关系数据库系统(ORDBS)是关系数据库与面向对象数据库的结合。

    • XML数据模型

      • 随着互联网发展,XML成为网上数据交换的标准。

      • 由结点标记树、操作和语义约束组成。

      • 商业关系数据库通过扩展关系代数支持XML数据管理。

    • RDF数据模型

      • 用于描述和注解万维网中的资源。

      • 由(主语,谓语,宾语)构成的三元组表示。

      • SPARQL是广泛采用的RDF查询语言。

13.3.2 数据库技术与相关技术相结合

  • 分布式数据库系统

    • 数据分布在计算机网络的不同计算机上。

    • 特点包括本地自治性、场地自治性与协作性。

    • 组成包括DDBMS、全局字典和分布目录、网络访问进程。

    • 面临的挑战:根据CAP理论,一致性、可用性、分区容错性三者不可兼得。

  • 并行数据库系统

    • 在并行机上运行,具有并行处理能力。

    • 发展阶段包括数据库机研究、通用并行机研究、并行数据在时间和空间并行性的研究。

    • 研究内容包括数据流方法、物理组织、并行数据操作算法、查询优化等。

    • 著名系统有 Arber、Bubba、Gamma、XPRS、Teradata 等。

13.3.3 面向领域的数据库新技术

  • 工程数据库

    • 存储和管理工程设计图形和文档。

    • 功能包括复杂对象表示、可扩展数据类型、支持工程数据存储和集成管理等。

  • 空间数据库

    • 存储和处理空间数据及其属性。

    • 特点包括包含空间位置及状态信息、拓扑关系信息。

    • 研究内容包括空间数据模型、空间数据查询、空间数据库系统、查询语言等。

13.4 数据库技术发展趋势

13.4.1 数据管理技术面临的挑战

  • 数据的变化

    • 数据海量化,要求系统具有高度的可扩展性和可伸缩性。

    • 数据类型越来越多样和异构。

    • 视觉听觉数据蕴含在流数据中,存在大量冗余和噪声。

  • 应用和需求的发展

    • 数据处理和应用领域从OLTP扩展到OLAP分析处理。

    • 从结构化数据的多维分析发展到非结构化数据的复杂分析和深度挖掘。

    • 计算机硬件的迅速发展,要求利用新的硬件技术满足海量数据存储和管理的需求。

13.4.2 数据管理技术的发展与展望

  • 大数据挑战:大数据给数据管理、处理和分析提出了全面挑战。

  • NoSQL技术

    • 非关系型、分布式、不保证满足ACID特性的一类数据管理系统。

    • 特点包括数据划分、放松ACID一致性约束、数据分区备份。

    • 存储模型包括 Key-Value、Column Family、文档模型、图模型

    • 2004年Google发布基于NoSQL技术的 MapReduce技术

  • 传统关系数据库:仍然提供高度一致性、精确性、系统可恢复性等关键特性,是事务处理系统的核心引擎。

13.5 小结

  • 数据库系统已经发展成为一个大家族。

  • 本章以 数据模型、新技术内容、应用领域 为三条主线,回顾了数据库发展的三个阶段。

  • 数据库的技术核心是数据管理。

  • 随着大数据时代的到来、新应用领域的需求不断增加以及硬件平台的飞速发展,各类数据库将不断涌现。

第14章 大数据管理

14.1 大数据概述

14.1.1 什么是大数据
  • 大数据定义:一般意义上,大数据指无法在可容忍的时间内用现有IT技术和软硬件工具对其进行感知、获取、管理、处理和服务的数据集合。大数据通常认为是PB或EB或更高量级的数据,包括结构化的、半结构化的和非结构化的数据。

  • 大数据分类:按大数据的应用类型分为海量交易数据(企业OLTP应用)、海量交互数据(社交网、传感器、全球定位系统、Web信息)和海量处理数据(企业OLAP应用)。

14.1.2 大数据的特征
  • 大数据的特征(4V)

    • 巨量(Volume):大数据的首要特征是数据量巨大,而且在持续、急剧地膨胀。主要来源有:科学研究、互联网应用和电子商务领域、传感器数据、网站点击流数据、移动设备数据、无线射频识别数据等。

    • 多样(Variety):数据的多样性通常是指异构的数据类型、不同的数据表示和语义解释。越来越多的应用所产生的数据类型不再是纯粹的关系数据,更多的是非结构化、半结构化的数据,如文本、图形、图像、音频、视频、网页、推特、和博客等。

    • 快变(Velocity):大数据的快变性也称为实时性,一方面指数据到达的速度很快,另一方面指能够进行处理的时间很短,或者要求响应速度很快,即实时响应。

    • 价值(Value):大数据的价值是潜在的、巨大的。大数据不仅具有经济价值和产业价值,还具有科学价值。这是大数据最重要特点,也是大数据的魅力所在。

14.2 大数据的应用

14.2.1 感知现在 预测未来—互联网文本大数据管理与挖掘
  • 互联网媒体文本大数据应用:时事探针:时事探针系统可以实时监控、收集互联网媒体数据,并对数据进行深入的挖掘和分析。例如“马航事件”等信息过载问题和“高考”等热点话题。

  • 互联网文本大数据管理的挑战:对于文本大数据处理,目前广泛使用的互联网搜索引擎只是对文本数据的简单索引和查找,不能满足用户对所关注的话题进行实时监测、深入分析以及决策支持等需求。

  • 互联网文本大数据管理系统:时事探针系统是一个面向互联网文本大数据的通用的管理和分析平台。整个系统分为离线处理和在线处理两个部分。其中离线部分是设计的重点,主要功能有:

    • 多源异构网络大数据的感知和获取。

    • 文档理解及结构化数据抽取和集成。

    • 数据存储和索引。

    • 离线主题文本立方体建立及更新。

  • 互联网文本大数据管理的特点

    • 互联网文本大数据蕴含着丰富的社会信息,可以看作是对真实社会的网络映射。

    • 实时、深入分析互联网文本大数据,帮助人们在海量数据中获取有价值的信息,发现蕴含的规律,可以更好地感知现在、预测未来。

    • 互联网文本大数据管理对大数据系统和技术的挑战是全面、跨学科领域的,需要创新,也需要继承传统数据管理技术和数据仓库分析技术的精华。

14.2.2 数据服务 实时推荐—基于大数据分析的用户建模
  • 面向用户建模的大数据系统架构:用户建模的目标是为了准确地把握用户的行为特征、兴趣爱好等,进而较为精准地向用户提供个性化地信息服务或信息推荐。面向用户建模的大数据系统架构如下:

    • 上层应用(信息推荐等)

    • 数据服务(用户兴趣模型表)

    • 在线分析 离线分析

    • 实时大数据 历史大数据

  • 数据分析:用户建模的基础工具

    • 一大类用户建模方法采用的是批处理方式的离线分析方法,对结构化或半结构化的历史日志数据进行SQL分析或者使用数据挖掘和机器学习的深度分析方法。

    • 另一大类用户建模方法则采用实时的在线分析方法,数据即来即分析,更强调数据的实时分析处理能力。

  • 数据服务:用户建模的价值体现

    • 模型建立来自对大数据的分析结果。

    • 数据处理既有对历史数据的离线分析和挖掘,又有对实时流数据的在线采集和分析。

    • 用户模型本身也是大数据,维度高,信息稀疏,用户模型的存储、管理是数据服务的重要任务,要满足大规模应用需求的高并发数据更新与读取。

14.3 大数据管理系统

14.3.1 NoSQL数据管理系统
  • NoSQL:是以互联网大数据应用为背景发展起来的分布式数据管理系统。NoSQL有两种解释:一种是Non-Relational,即非关系数据库;另一种是Not Only SQL,即数据管理技术不仅仅是SQL。目前第二种解释更为流行。

  • NoSQL系统支持的数据模型:通常分为Key-Value模型、BigTable模型、文档模型和图模型4种模型。

14.3.2 NewSQL数据库系统
  • NewSQL系统:是融合了NoSQL系统和传统数据库事务管理功能的新型数据库系统。

14.3.3 MapReduce技术
  • MapReduce技术:是Google公司于2004年提出的大规模并行计算解决方案,主要应用于大规模廉价集群上的大数据并行处理。MapReduce是一种并行编程模型。它把计算过程分解为两个阶段,即Map阶段和Reduce阶段。

14.3.4 大数据管理系统的新格局
  • 面向操作型应用的关系数据库技术

  • 面向分析型应用的关系数据库技术

  • 面向操作型应用的NoSQL技术

  • 面向分析型应用的MapReduce技术

14.4 小结

  • 大数据的概念。

  • 大数据特点及大数据管理和大数据系统的技术需求和挑战。

  • NoSQL系统、NewSQL系统和MapReduce技术等。


第15章 内存数据库系统

15.1 概述

  • 内存数据库:是将内存作为主存储设备的数据库系统,也称主存数据库、In-Memory DataBase等。内存作为数据存储设备,磁盘是数据的永久存储及后备存储设备。

15.2 内存数据库的发展历史

  • 内存数据库的雏形期:1969年IBM公司研制了世界上最早的层次数据库管理系统—IMS,其中Fast Path部分是一个支持内存驻留数据的商业化数据库。

  • 内存数据库的研究发展期:1984年—1990年提出了主存数据库的概念,并研发出了OBE、MM DBMS、System M等内存数据库。

  • 内存数据库的产品成长期:1994年以来随着硬件的发展,内存数据库快速发展,第一个商业化的主存数据库Polyhedra等产品纷纷出现。

15.3 内存数据库的特性

  • 高吞吐率和低访问延迟:数据可直接被处理器访问,不需要磁盘数据库的缓冲区机制。

  • 并行处理能力:多通道存储器技术,理论上每增加一条通道,数据发送性能相较于单通道而言会增加一倍。目前为四通道技术内存访问机制。

  • 硬件相关性:内存数据库的性能受到硬件特性的直接影响,主要是多核处理器、高性能存储器、高速连通。

15.4 内存数据库的关键技术

  • 数据存储:行存储模型、列存储模型、混合模型等。

  • 查询处理及优化

    • 查询处理性能主要由内存访问性能和内存处理性能决定。

    • 面向cache特性的查询处理与优化技术。

    • 索引技术。

    • 面向多核的查询处理技术。

    • 面向众核的查询处理技术。

  • 并发与恢复

    • 并发控制:与磁盘数据库的并发控制基本一样。内存数据库事务执行时间较短,系统冲突较少,可以采用较大的封锁粒度、乐观加锁方式等并发控制方法。

    • 恢复机制:内存的数据易丢失,所以数据和日志需要在磁盘等非易失性存储介质中。

15.5 小结

  • 硬件的发展为内存数据库提供良好的平台。

  • 内存OLTP数据库软件比较成熟,应用在了金融、电信等实时响应要求高的行业。

  • 当前服务器支持TB级内存,在数据压缩的技术下,内存数据库能够支持数倍甚至数十倍于内存的大数据处理任务。


第16章 数据仓库与联机分析处理技术

16.1 数据仓库技术

  • 数据仓库定义:数据仓库是一个用以更好地支持企业(或组织)决策分析处理的、面向主题的、集成的、不可更新的、随时间不断变化的数据集合。本质上和数据库一样,是长期储存在计算机内的、有组织、可共享的数据集合。

  • 数据仓库的基本特征

    • 数据仓库的数据是面向主题的:面向主题的数据组织方式是根据分析要求将数据组织成一个完备的分析域,即主题域。

    • 数据仓库的数据是集成的:数据仓库的数据是从原有的分散的数据库数据中抽取出来的,数据在进入数据仓库前要进行加工与集成,统一于综合。

    • 数据仓库的数据是不可更新的:数据仓库主要供决策分析之用,所涉及的数据操作主要是数据查询,一般情况下并不进行修改操作。是指用户进行分析处理时不进行数据更新,不是说数据仓库的整个生命周期中数据不变。

    • 数据仓库的数据是随时间不断变化的

      • 随时间变化数据内容不断增加。

      • 随时间变化旧的数据内容被删除。

      • 随时间变化数据被不断的重新组合。

  • 数据仓库中的数据组织

  • 数据仓库系统的体系结构

16.2 联机分析处理技术

  • 多维数据模型:数据分析时用户的数据视图,是面向分析的数据模型,用于给分析人员提供多种观察的视角和面向分析的操作。例如电器商品销售数据按地区、时间、电器商品种类、销售额直观表示。

  • 多维分析操作:常用的OLAP多维分析操作有切片(slice)、切块(dice)、旋转(pivot)、向上综合(roll-up)、向下钻取(drill-down)等。

  • OLAP的实现方式

    • MOLAP结构:以多维立方体CUBE来组织数据。

    • ROLAP结构:用关系的表来组织和存储多维数据,星形模式和雪片模式。

    • HOLAP结构:是MOLAP结构和ROLAP结构的混合。

16.3 数据挖掘技术

  • 数据挖掘的概念:数据挖掘是从大量数据中发现并提取隐藏在内的、人们事先不知道的但又可能有用的信息和知识的一种新技术。目的是帮助决策者寻找数据间潜在的关联,发现经营者被忽略的要素。

  • 数据挖掘和传统分析方法的区别:本质区别是数据挖掘是在没有明确假设的前提下去挖掘信息,发现知识。数据挖掘所得到的信息应具有事先未知、有效和可实用3个特征。

  • 数据挖掘的数据源:从数据仓库中来、从数据库中来。

16.4 大数据时代的新型数据仓库

  • 系统需求的变化

    • 数据量急剧增长,由TB升至PB升至ZB,并仍爆炸式增长。

    • 数据类型多样,必须能够处理大量的结构化和半结构化的数据。

    • 决策分析复杂,由常规分析转为深度分析。

    • 底层硬件环境变化,多核处理器、大内存、高速网络。

  • 传统数据仓库所面临的问题

    • 数据移动代价过高。

    • 不能快速适应变化。

  • 大数据时代的新型数据仓库:新型数据仓库需具备以下的特性:

    • 高度可扩展:横向大规模可扩展,大规模并行处理。

    • 高性能:快速响应复杂查询和分析。

    • 高度容错性:查询失败时,只需重做部分工作。

    • 支持异构环境:对硬件平台一致性要求不高,适应能力强。

    • 较低的分析延迟:业务需要变化时,能快速反应。

    • 易用且开发接口:既能方便查询,又能处理复杂分析。

    • 较低成本:较高性价比。

    • 向下兼容性:支持传统的BI工具。

16.5 小结

  • 数据仓库定义、基本特征、数据组织、体系结构。

  • 联机分析处理技术。多维数据模型、多维分析操作、OLAP的实现方式。

  • 数据挖掘技术。数据挖掘的概念,数据挖掘和传统分析方法的区别,数据挖掘的数据源。

  • 新型数据仓库需具备的特性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值