《数据库系统概论》学习笔记

第0章 脚手架

0.1 写在前面

本学习笔记的主要用途,是来回顾数据库的一些基本理论知识和SQL语句。

学习笔记的主要参考文献,为王珊著的《数据库系统概论》(第5版,2014)和教育部考试中心出版的《全国计算机等级考试三级教程——数据库技术》(2022年版),其中以王珊著的《数据库系统概论》为主要架构。其他具体内容可能会涉及到的其他资料和文章,我会附在相应小节的最后。

相对应地,我也会选择并写出一些自己实践过程中遇到的bug和问题,并附带相应的解决方法。

首次撰写博客,如有不足之处还望批评指正。

0.2 《数据库系统概论》的大致架构介绍

在《数据库系统概论》一书中,作者将全书分为了四个大的篇章,分别是:

  • 第一篇 基础篇

  • 第二篇 设计与应用开发篇

  • 第三篇 系统篇

  • 第四篇 新技术篇

其中,第一篇在介绍类型各异的数据库的基础上,详细介绍了关系型数据库的基础内容,及其标准语言SQL(Structured Query Language,结构化查询语言)的许多操作实例,并在之后讲述了数据库的安全性和完整性。

第二篇是数据库设计开发的关键内容,包括了关系数据理论、数据库设计和数据库编程部分。关系数据理论是数据库设计开发的基础。数据库设计是一个全流程的设计过程,从需求分析开始,到数据库的实施和维护的循环。数据库编程(SQL编程技术)则可以有效克服SQL语言实现复杂应用方面的不足,提高应用系统和数据库管理系统间的互操作性。

第三篇主要是前两篇内容基础上的一个提高。关系查询处理和查询优化、数据库恢复技术与并发控制,都是在实际使用数据库的过程中需要不断改进的。数据库管理系统则将上述功能综合起来,形成了一个更加严谨的系统。

第四篇则在讲述数据库的发展历史的基础上,针对NoSQL、内存数据库、数据仓库与联机分析处理技术等方面进行了介绍,并联系了目前的大数据时代的新格局。

0.3 《全国计算机等级考试三级教程——数据库技术》的大致架构介绍

与0.2节中参考书的体例不同,该教程的体例更多从数据库的全流程设计过程入手,按不同阶段安排了不同的内容,也介绍了0.2节内容之外的其他部分知识。但内容在大体上是类似的。

该书的目录如下所示:

  • 第1章 数据库应用系统开发方法

  • 第2章 需求分析

  • 第3章 数据库结构设计

  • 第4章 数据库应用系统功能设计与实施

  • 第5章 UML与数据库应用系统

  • 第6章 高级数据查询

  • 第7章 数据库及数据库对象

  • 第8章 数据库后台编程技术

  • 第9章 安全管理

  • 第10章 数据库运行维护与优化

  • 第11章 故障管理

  • 第12章 备份与恢复数据库

  • 第13章 大规模数据库架构

  • 第14章 数据仓库与数据挖掘

  • 附录4 系统提供的常用函数

第1章 绪论

1.0 本章内容

本章初步讲解数据库的基本概念,介绍数据类型的组成要素和常用的数据模型、数据库系统的三级模式结构和数据库系统的主要组成部分。

1.1 数据库的4个基本概念

数据、数据库、数据库管理系统和数据库系统是与数据库技术密切相关的4个基本概念。

1.数据

描述事物的符号记录称为数据。数据有多种表现形式,它们都可以经过数字化后存入计算机。

数据的表现形式还不能完全表达其内容,需要经过解释。数据和关于数据的解释是不可分的。数据的含义称为数据的语义,数据与其语义是不可分的。

记录是计算机中表示和存储数据的一种格式或一种方法。

2.数据库(Database,DB)

严格地讲,数据库是长期存储在计算机内、有组织的、可共享的大量数据的集合。数据库中的数据按一定的数据模型组织、描述和储存,具有较小的冗余度、较高的数据独立性和易扩展性,并可为各种用户共享。

概括地讲,数据库存储具有永久存储、有组织和可共享三个基本特点。

3.数据库管理系统(Database Management System,DBMS)

数据库管理系统是位于用户与操作系统之间的一层数据管理软件。数据库管理系统和操作系统一样是计算机的基础软件,也是一个大型复杂的软件系统。

DBMS的主要功能包括:

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

(2)数据组织、存储和管理:DBMS要分类组织、存储和管理各种数据,包括数据字典、用户数据、数据的存储路径等。要确定以何种文件结构和存取方式在存储级上组织这些数据,如何实现数据之间的联系。

数据组织和存储的基本目标是提高存储空间利用率和方便存取,提供多种存取方法(如索引查找、hash查找、顺序查找等)来提高存取效率。

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

(4)数据库的事务管理和运行管理:保证事务的正确运行,保证数据的安全性、完整性、多用户对数据的并发使用及发生故障的系统恢复。

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

(6)其他功能:包括DBMS与网络中其他软件系统的通信功能,一个DBMS与另一个DBMS或文件系统的数据转换功能,异构数据库之间的互访和互操作功能等。

4.数据库系统(Database System,DBS)

数据库系统是由数据库、DBMS(及其应用开发工具)、应用程序和数据库管理员(Database Administrator,DBA)组成的存储、管理、处理和维护数据的系统。

数据库的建立、使用和维护等工作只靠一个DBMS远远不够,还要有专门的人员来完成,这些人被称为数据库管理员。

数据库系统可以用图1.1表示。其中,DB提供数据的存储功能,DBMS提供数据的组织、存取、管理和维护等基础功能,数据库应用系统根据应用需求使用数据库,DBA负责全面管理DBS。图1.2是引入数据库后计算机系统的层次结构。

在一般不引起混淆的情况下,人们常把数据库系统简称为数据库。

《数据库系统概论》学习笔记_第1张图片

1.2 数据管理三个阶段的比较

人工管理阶段

文件系统阶段

数据库系统阶段

背景

应用背景

科学计算

科学计算、数据管理

大规模数据管理

硬件背景

无直接存取存储设备

磁盘、磁鼓

大容量磁盘、磁盘阵列

软件背景

没有操作系统

有文件系统

有数据库管理系统

处理方式

批处理

联机实时处理、批处理

联机实时处理、分布处理、批处理

特点

数据的管理者

用户(程序员)

文件系统

数据库管理系统

数据面向的对象

某一应用程序(应用程序与数据之间一一对应)

某一应用

现实世界(一个部门、企业、跨国组织等)

数据的共享程度

无共享,冗余度极大

共享性差,冗余度大

共享性高,冗余度小

数据的独立性

不独立,完全依赖于程序

独立性差

具有高度的物理独立性和一定的逻辑独立性

数据的结构化

无结构

记录内有结构、整体无结构

整体结构化,用数据模型描述

数据控制能力

应用程序自己控制

应用程序自己控制

由DBMS提供数据安全性、完整性、并发控制和恢复能力

从文件系统到数据库系统标志着数据管理技术的飞跃。

1.3 数据库系统的特点

1.数据结构化

数据库系统实现整体数据的结构化,这是数据库的主要特征之一,也是数据库系统与文件系统的本质区别。

所谓“整体”结构化是指数据库中的数据不再仅仅针对某一个应用,而是面向整个组织或企业;不仅数据内部是结构化的,而且整体是结构化的,数据之间是具有联系的。

数据库系统中,不仅数据是整体结构化的,而且存取数据的方式也很灵活,可以存取数据库中的某一个或一组数据项、一个记录或一组记录;而在文件系统中,数据的存取单位是记录,粒度不能细到数据项。

2.数据库的共享性高、冗余度低且易扩充

数据库系统从整体角度看待和描述数据,数据不再面向某个应用而是面向整个系统,因此数据可以被多个用户、多个应用共享使用。数据共享可以大大减少数据冗余,节约存储空间。数据共享还能避免数据之间的不相容性与不一致性。

所谓数据的不一致性是指同一数据不同副本的值不一样。在数据库中,数据共享减少了由于数据冗余造成的不一致现象。

由于数据面向整个系统,是有结构的数据,不仅可以被多个应用共享使用,而且容易增加新的应用,这就使得数据库系统弹性大,易于扩充,可以适应各种用户的要求。可以选取整体数据的各子集用于不同的应用系统,当应用需求改变或增加时,只要重新选取不同的自己或加上一部分数据便可以满足新的需求。

3.数据独立性高

数据独立性是借助数据库管理数据的一个显著优点,它已成为数据库领域中一个常用术语和重要概念,包括数据的物理独立性和逻辑独立性。数据独立性是由DBMS提供的二级映像功能来保证的。

物理独立性是指用户的应用程序与数据库中数据的物理存储是相互独立的。用户程序不需要了解,应用程序要处理的只是数据的逻辑结构,这样当数据的物理存储改变时应用程序不用改变。

逻辑独立性是指用户的应用程序与数据库的逻辑结构是相互独立的。也就是说,数据的逻辑结构改变时,用户程序也可以不变。

4.数据由数据库管理系统统一管理和控制

数据库的共享会带来数据库的安全隐患,而数据库的共享是并发的共享,这又会带来不同用户间相互干扰的隐患。另外,数据库中数据的正确与一致也必须得到保障。

(1)数据的安全性保护:数据的安全性是指保护数据以防不合法使用造成的数据泄密和破坏。每个用户只能按规定对某些数据以某些方式进行使用和处理。

(2)数据的完整性检查:数据的完整性指数据的正确性、有效性和相容性。完整性检查将数据控制在有效的范围内,并保证数据之间满足一定的关系。

(3)并发控制:当多个用户的并发进程同时存取、修改数据库时,可能会发生互相干扰而得到错误的结果或使得数据库的完整性遭到破坏,因此必须对多用户的并发操作加以控制和协调。

(4)数据库恢复:计算机系统的硬件故障、软件故障、操作员的失误以及故意破坏也会影响数据库中数据的正确性,甚至造成数据库部分或全部数据的丢失。数据库管理系统必须具有将数据库从错误状态恢复到某一已知的正确状态(亦称为完整状态或致状态)的功能,这就是数据库的恢复功能。

5.总结

综上所述,数据库是长期存储在计算机内有组织、大量、共享的数据集合。它可以供各种用户共享,具有最小冗余度和较高的数据独立性。数据库管理系统在数据库建立、运用和维护时对数据库进行统一控制,以保证数据的完整性和安全性,并在多用户同时使用数据库时进行并发控制,在发生故障后对数据库进行恢复。

数据库系统的出现使信息系统从以加工数据的程序为中心转向围绕共享的数据库为中心的新阶段。这样既便于数据的集中管理,又能简化应用程序的研制和维护,提高了数据的利用率和相容性,提高了决策的可靠性。

1.4 数据模型

数据模型也是一种模型,它是对现实世界数据特征的抽象。数据模型是数据库系统的核心和基础。

1.两类数据模型

开发实施数据库应用系统中也需要使用不同的数据类型:概念模型、逻辑模型和物理模型。

根据模型应用的不同目的,可以将这些模型划分为两大类,它们分别属于两个不同的层次。第一类是概念模型,第二类是逻辑模型和物理模型。

第一类概念模型,也称为信息模型,它是按用户的观点来对数据和信息建模,主要用于数据库设计。

第二类中,逻辑模型主要包括层次模型、网状模型、关系模型、面向对象数据类型和对象关系数据模型、半结构化数据模型等。它按照计算机系统的观点对数据建模,主要用于数据库管理系统的实现;物理模型是对数据最底层的抽象,它描述数据在系统内部的表示方式和存取方法,是面向计算机系统的。数据库设计人员要了解和选择物理模型,最终用户则不必考虑物理级的细节。

2.概念模型

概念模型用于信息世界的建模,是现实世界到信息世界的第一层抽象,是数据库设计人员进行数据库设计的有力工具,也是数据库设计人员和用户之间进行交流的语言,因此概念模型一方面应该具有较强的语义表达能力,能够方便、直接地表达应用中的各种语义知识,另一方面它还应该简单、清晰、易于用户理解。

· 信息世界中的基本概念

(1)实体:客观存在并可以相互区别的事物称为实体。实体可以是具体的人、事、物,也可以是抽象的概念或联系。

(2)属性:实体所具有的某一特性成为属性。一个实体可以由若干个属性来刻画。

(3)码:唯一标识实体的属性集称为码。

(4)实体型:具有相同属性的实体必然具有共同的特征和性质。用实体名及其属性名集合来抽象和刻画同类实体,称为实体型。例如,学生(学号,姓名)就是一个实体型。

(5)实体集:同一类型实体的集合称为实体集。例如,全体学生就是一个实体集。

(6)联系:实体内部的联系通常是指组成实体的各属性之间的联系,实体之间的联系通常是指不同实体集之间的联系。

实体之间的联系有一对一、一对多和多对多等多种类型。

如果对于实体集 A中的每一个实体, 实体集B中至多有一个 (也可以没有) 实体与之联系,反之亦然,则称实体集A与实体集B具有一对一联系。

如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系,反之,对于实体集B中的每一个实体,实体集A中至多只有一个实体与之联系,则称实体集A与实体集B有一对多联系。

如果对于实体集A中的每一个实体,实体集B中有n个实体(n≥0)与之联系,反之,对于实体集B中的每一个实体,实体集A中也有m个实体(m≥0)与之联系,则称实体集A与实体集B具有多对多联系。例如一门课程可以同时有若干名学生选修,而一个学生可以同时选修多门课程,则课程实体与学生实体具有多对多联系。

· 概念模型的一种表示方法:实体-联系方法

概念模型是对信息世界建模,所以概念模型应该能够方便、准确地表示出上述信息世界中的常用概念。概念模型的表示方法很多,其中最为常用的是P.P.S.Chen于1976年提出的实体联系方法(Entity-Relationship approach)。该方法用E-R图(E-R diagram)来描述现实世界的概念模型,E-R方法也称为E-R模型。

3.数据模型的组成要素

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

· 数据结构

数据结构描述数据库的组成对象以及对象之间的关系。

数据结构描述的内容有两类:一类是与对象的类型、内容、性质有关的,如网状模型中的数据项、记录,关系模型中的域、属性、关系等;一类是与数据之间联系有关的对象,如网状模型中的系型(set type)。

数据结构是刻画一个数据模型性质最重要的方面。因此在数据库系统中,人们通常按照其数据结构的类型来命名数据模型。例如层次结构、网状结构和关系结构的数据模型分别命名为层次模型、网状模型和关系模型。

总之,数据结构是所描述的对象类型的集合,是对系统静态特性的描述。

· 数据操作

数据操作是指对数据库中各种对象(型)的实例(值)允许执行的操作的集合,包括操作及有关的操作规则。

数据库主要有查询和更新(包括插入、删除、修改)两大类操作。数据模型必须定义这些操作的确切含义、操作符号、操作规则(如优先级)以及实现操作的语言。

数据操作是对系统动态特性的描述。

· 数据的完整性约束条件

数据的完整性约束条件是一组完整性规则。完整性规则是给定的数据模型中数据及其联系所具有的制约和依存规则,用以限定符合数据模型的数据库状态及其状态的变化,以保证数据的正确、有效和相容。

数据模型应该反映和规定其必须遵守的基本的和通用的完整性约束条件。例如,在关系模型中,任何关系必须满足实体完整性和参照完整性两个条件。

此外,数据模型还应该提供定义完整性约束条件的机制,以反映具体应用所涉及的数据必须遵守的特定的语义约束条件。

4.常用的数据模型

数据库领域中主要的逻辑数据模型有:

  • 层次模型

  • 网状模型

  • 关系模型

  • 面向对象数据模型

  • 对象关系数据模型

  • 半结构化数据模型

其中,层次模型和网状模型统称为格式化模型。格式化模型的数据库系统在20世纪70年代至80年代初非常流行,在数据库系统产品中占据了主导地位,但现在已经逐渐被关系模型的数据库系统取代。

20世纪80年代以来,面向对象的方法和技术在计算机各个领域,包括程序设计语言、软件工程、信息系统设计、计算机硬件设计等方面都产生了深远的影响,也促进数据库中面向对象数据模型的研究和发展。许多关系数据库厂商为了支持面向对象模型,对关系模型做了扩展,从而产生了对象关系数据模型。

随着Internet的迅速发展,Web上各种半结构化、非结构化数据源已经成为重要的信息来源,产生了以XML为代表的半结构化数据模型和非结构化数据模型。

在格式化模型中,实体用记录表示,实体的属性对应记录的数据项(或字段)。实体之间的联系在格式化模型中转换成记录之间的两两联系。

在格式化模型中,数据结构的单位是基本层次联系,即两个记录及其它们之间的一对多(包括一对一)的联系。联系的始点称为双亲结点,联系的重点称为子女结点。

5.层次模型

层次模型是数据库系统中最早出现的数据模型,层次数据库系统采用层次模型作为数据的组织方式。层次数据库系统的典型代表是IBM公司的IMS (Information ManagementSystem),这是1968年IBM公司推出的第一个大型商用数据库管理系统,曾经得到广泛的使用。

层次模型用树形结构来表示各类实体以及实体间的联系。现实世界中许多实体之间的联系本来就呈现出一种很自然的层次关系,如行政机构、家族关系等。

(1)层次模型的数据结构

在数据库中,定义满足下面两个条件的基本层次联系的集合为层次模型:

(1)有且只有一个结点没有双亲结点,这个结点称为根结点;

(2)根以外的其他结点有且只有一个双亲结点。

在层次模型中,每个结点表示一个记录类型,记录类型之间的联系用结点之间的连线(有向边)表示,这种联系是父子之间的一对多的联系。这就使得层次数据库系统只能处理一对多的实体联系。

每个记录类型可包含若干个字段,这里记录类型描述的是实体,字段描述实体的属性。各个记录类型及其字段都必须命名。各个记录类型、同记录类型中各个字段不能同名。每个记录类型可以定义一个排序字段,也称为码字段,如果定义该排序字段的值是唯一的,则它能唯一地标识 一个记录值。

一个层次模型在理论上可以包含任意有限个记录类型和字段,但任何实际的系统都会因为存储容量或实现复杂度而限制层次模型中包含的记录类型个数和字段的个数。

层次模型像一棵倒立的树,结点的双亲是唯一的。

层次模型的一个基本的特点是,任何一个给定的记录值只能按其层次路径查看,没有一个子女记录值能够脱离双亲记录值而独立存在。

(2)层次模型的数据操纵与完整性约束

层次模型的数据操纵主要有查询、插入、删除和更新。 进行插入、删除、更新操作时要满足层次模型的完整性约束条件。

进行插入操作时,如果没有相应的双亲结点值就不能插入它的子女结点值;进行删除操作时,如果删除双亲结点值,则相应的子女结点值也将被同时删除。

(3)层次模型的优缺点

层次模型的优点主要有:

(1)层次模型的数据结构比较简单清晰。

(2)层次数据库的查询效率高。因为层次模型中记录之间的联系用有向边表示,这种联系在DBMS中常常用指针来实现。因此这种联系也就是记录之间的存取路径。当要存取某个结点的记录值,DBMS就沿着这一.条路径很快找到该记录值,所以层次数据库的性能优于关系数据库,不低于网状数据库。

(3)层次数据模型提供了良好的完整性支持。

可见,用层次模型对具有一对多的层次联系的部门描述非常自然、直观,容易理解。这是层次数据库的突出优点。

层次模型的缺点主要有:

(1)现实世界中很多联系是非层次性的,如结点之间具有多对多联系,不适合用层次模型表示。

(2)如果一个结点具有多个双亲结点等,用层次模型表示这类联系就很笨拙,只能通过引入冗余数据(易产生不一致性)或创建非自然的数据结构(引入虚拟结点)来解决。对插入和删除操作的限制比较多,因此应用程序的编写比较复杂。

(3)查询子女结点必须通过双亲结点。

(4)由于结构严密,层次命令趋于程序化。

6.网状模型

在现实世界中事物之间的联系更多的是非层次关系,用层次模型表示非树形结构是很不直接的,网状模型则可以克服这一弊病。

网状数据库系统采用网状模型作为数据的组织方式。网状数据模型的典型代表是DBTG系统,亦称为CODASYL系统。

(1)网状模型的数据结构

在数据库中,把满足以下两个条件的基本层次联系集合称为网状模型:

(1)允许一个以上的结点无双亲;

(2)一个结点可以有多于一个的双亲。

网状模型是一种比层次模型更具普遍性的结构。它去掉了层次模型的两个限制,允许多个结点没有双亲结点,允许结点有多个双亲结点:此外它还允许两个结点之间有多种联系(称之为复合联系)。因此,网状模型可以更直接地去描述现实世界。而层次模型实际上是网状模型的一个特例。

与层次模型一样,网状模型中每个结点表示一个记录类型(实体),每个记录类型可包含若干个字段(实体的属性),结点间的连线表示记录类型(实体)之间一对多的父子联系。

从定义可以看出,层次模型中子女结点与双亲结点的联系是唯一的,而在网状模型中这种联系可以不唯一。因此要为每个联系命名,并指出与该联系有关的双亲记录和子女记录。

(2)网状模型的数据操纵与完整性约束

网状模型一般来说没有层次模型那样严格的完整性约束条件,但具体的网状数据库系统对数据操纵都加了一些限制,提供了一定的完整性约束。

例如,DBTG在模式数据定义语言中提供了定义DBTG数据库完整性的若干概念和语句,主要有:

(1)支持记录码的概念,码即唯一标识记录的数据项的集合。例如,学生记录(如图1.13)中学号是码,因此数据库中不允许学生记录中学号出现重复值。

(2)保证一个联系中双亲记录和子女记录之间是一对多的联系。

(3)可以支持双亲记录和子女记录之间的某些约束条件。例如,有些子女记录要求双亲记录存在才能插入,双亲记录删除时也连同删除。DBTG提供了“属籍类别”的概念来描述这类约束条件。

(3)网状模型的优缺点

网状模型的优点主要有:

(1)能够更为直接地描述现实世界,如一个结点可以有多个双亲,结点之间可以有多种联系。

(2)具有良好的性能,存取效率较高。

网状模型的缺点主要有:

(1)结构比较复杂,而且随着应用环境的扩大,数据库的结构就变得越来越复杂,不利于最终用户掌握。

(2)网状模型的DDL、DML复杂,并且要嵌入某一种高级语言(如COBOL、C)中。用户不容易掌握,不容易使用。

(3)由于记录之间的联系是通过存取路径实现的,应用程序在访问数据时必须选择适当的存取路径,因此用户必须了解系统结构的细节,加重了编写应用程序的负担。

7.关系模型

(1)关系模型的数据结构

关系模型与以往的模型不同,它是建立在严格的数学概念的基础上的。从用户观点看,关系模型由一组关系组成。每个关系的数据结构是一张规范化的二维表。

  • 关系:一个关系对应通常说的一张表。

  • 元组:表中的一行即为一个元组。

  • 属性:表中的一列即为一个属性,给每一个属性起一个名称即属性名。

  • 码:也称为码键。表中的某个属性组,它可以唯一确定一个元组。

  • 域:域是一组具有相同数据类型的值的集合。属性的取值范围来自某个域。例如,性别的域为(男,女)。

  • 分量:元组中的一个属性值。

  • 关系模式:对关系的描述,一般表示为:关系名(属性1,属性2,…,属性n)。

关系模型要求关系必须是规范化的,即要求关系必须满足一定的规范条件,这些规范条件中最基本的一条就是,关系的每一个分量必须是一个不可分的数据项。也就是说,不允许表中还有表。

关系术语与一般表格中的术语的对应关系如下所示:

关系数据

一般标格的术语

关系名

表名

关系模式

表头(表格的描述)

关系

(一张)二维表

元组

记录或行

属性

属性名

列名

属性值

列值

分量

一条记录中的一个列值

非规范关系

表中有表(大表中嵌有小表)

(2)关系模型的数据操纵与完整性约束

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

关系模型中的数据操作是集合操作,操作对象和操作结果都是关系,即若干元组的集合,而不像格式化模型中那样是单记录的操作方式。另方面,关系模型把存取路径向用户隐蔽起来,用户只要指出“干什么”或“找什么”,不必详细说明“怎么干”或“怎么找”,从而大大地提高了数据的独立性,提高了用户生产率。

(3)关系模型的优缺点

关系模型具有下列优点:

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

(2)关系模型的概念单一。无论实体还是实体之间的联系都用关系来表示。对数据的检索和更新结果也是关系(即表)。所以其数据结构简单、清晰,用户易懂易用。

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

所以关系模型诞生以后发展迅速,深受用户的喜爱。

当然,关系模型也有缺点,例如,由于存取路径对用户是隐蔽的,查询效率往往不如格式化数据模型。为了提高性能,数据库管理系统必须对用户的查询请求进行优化,因此增加了开发数据库管理系统的难度。不过用户不必考虑这些系统内部的优化技术细节。

1.5 数据库系统的结构

考察数据库系统的结构可以有多种不同的层次或不同的角度。从数据库应用开发人员角度看,数据库系统通常采用三级模式结构,这是数据库系统内部的系统结构。从数据库最终用户角度看,数据库系统的结构分为单用户结构、主从式结构、分布式结构、客户-服务器、浏览器应用服务器/数据库服务器多层结构等。这是数据库系统外部的体系结构。

本节介绍数据库系统的模式结构。

1.数据库系统模型的概念

在数据模型中有“型”(type)和“值”(value)的概念。型是指对某一类数据的结构和属性的说明,值,是型的一个具体赋值。

模式(schema)是数据库中全体数据的逻辑结构和特征的描述,它仅仅涉及型的描述,不涉及具体的值。模式的一个具体值称为模式的一个实例(instance)。同一个模式可以有很多实例。模式是相对稳定的,而实例是相对变动的,因为数据库中的数据是在不断更新的。模式反映的是数据的结构及其联系,而实例反映的是数据库某一时刻的状态。

虽然实际的数据库管理系统产品种类很多,它们支持不同的数据模型,使用不同的数据库语言,建立在不同的操作系统之上,数据的存储结构也各不相同,但它们在体系结构上通常都具有相同的特征,即采用三级模式结构(早期微机上的小型数据库系统除外)并提供两级映像功能。

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

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

(1)模式

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

模式实际上是数据库数据在逻辑级上的视图。一个数据库只有一个模式。数据库模式以某一种数据模型为基础,统综合地考虑了所有用户的需求,并将这些需求有机地结合成一个逻辑整体。定义模式时不仅要定义数据的逻辑结构,例如数据记录由哪些数据项构成,数据项的名字、类型、取值范围等;而且要定义数据之间的联系,定义与数据有关的安全性、完整性要求。

数据库管理系统提供模式数据定义语言(模式DDL)来严格地定义模式。

(2)外模式

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

外模式通常是模式的子集。一个数据库可以有多个外模式。由于它是各个用户的数据视图,如果不同的用户在应用需求、看待数据的方式、对数据保密的要求等方面存在差异,则其外模式描述就是不同的。即使对模式中同一数据,在外模式中的结构、类型、长度、保密级别等都可以不同。另一方面,同一外模式也可以为某一用户的多个应用系统所使用,但一个应用程序只能使用一个外模式。

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

数据库管理系统提供外模式数据定义语言(外模式DDL)来严格地定义外模式。

(3)内模式

内模式也称存储模式(storage schema), 一个 数据库只有一个内模式。它是数据物理结构和存储方式的描述,是数据在数据库内部的组织方式。例如,记录的存储方式是堆存储还是按照某个(些)属性值的升(降)序存储,或按照属性值聚簇(cluster) 存储;索引按照什么方式组织,是B+树索引还是hash索引;数据是否压缩存储,是否加密;数据的存储记录结构有何规定,如定长结构或变长结构,一个记录不能跨物理页存储;等等。

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

数据库系统的三级模式是数据的三个抽象级别,它把数据的具体组织留给数据库管理系统管理,使用户能逻辑地、抽象地处理数据,而不必关心数据在计算机中的具体表示方式与存储方式。为了能够在系统内部实现这三个抽象层次的联系和转换,数据库管理系统在这三级模式之间提供了两层映像:外模式/模式映像模式/内模式映像

正是这两层映像保证了数据库系统中的数据能够具有较高的逻辑独立性和物理独立性

(1)外模式/模式映像

模式描述的是数据的全局逻辑结构,外模式描述的是数据的局部逻辑结构。对应于同一个模式可以有任意多个外模式。对于每一个外模式,数据库系统都有一个外模式/模式映像,它定义了该外模式与模式之间的对应关系。这些映像定义通常包含在各自外模式的描述中。

当模式改变时(例如增加新的关系、新的属性、改变属性的数据类型等),由数据库管理员对各个外模式/模式的映像作相应改变,可以使外模式保持不变。应用程序是依据数据的外模式编写的,从而应用程序不必修改,保证了数据与程序的逻辑独立性,简称数据的逻辑独立性

(2)模式/内模式映像

数据库中只有一个模式,也只有一个内模式,所以模式/内模式映像是唯一的,它定义了数据全局逻辑结构与存储结构之间的对应关系。例如,说明逻辑记录和字段在内部是如何表示的。该映像定义通常包含在模式描述中。当数据库的存储结构改变时(例如选用了另一种存储结构),由数据库管理员对模式/内模式映像作相应改变,可以使模式保持不变,从而应用程序也不必改变。保证了数据与程序的物理独立性,简称数据的物理独立性

在数据库的三级模式结构中,数据库模式即全局逻辑结构是数据库的中心与关键,它独立于数据库的其他层次。因此设计数据库模式结构时应首先确定数据库的逻辑模式。

数据库的内模式依赖于它的全局逻辑结构,但独立于数据库的用户视图,即外模式,也独立于具体的存储设备。它是将全局逻辑结构中所定义的数据结构及其联系按照一定的物理存储策略进行组织,以达到较好的时间与空间效率。

数据库的外模式面向具体的应用程序,它定义在逻辑模式之上,但独立于存储模式和存储设备。当应用需求发生较大变化,相应的外模式不能满足其视图要求时,该外模式就得做相应改动,所以设计外模式时应充分考虑到应用的扩充性。

特定的应用程序是在外模式描述的数据结构上编制的,它依赖于特定的外模式,与数据库的模式和存储结构独立。不同的应用程序有时可以共用同一个外模式。数据库的二级映像保证了数据库外模式的稳定性,从而从底层保证了应用程序的稳定性,除非应用需求本身发生变化,否则应用程序一般不需要修改。

数据与程序之间的独立性使得数据的定义和描述可以从应用程序中分离出去。另外,由于数据的存取由数据库管理系统管理,从而简化了应用程序的编制,大大减少了应用程序的维护和修改。

1.6 数据库系统的组成

1.硬件平台及数据库

由于数据库系统的数据量都很大,加之数据库管理系统丰富的功能使得其自身的规模也很大,因此整个数据库系统对硬件资源提出了较高的要求,这些要求是:

(1)要有足够大的内存,存放操作系统、数据库管理系统的核心模块、数据缓冲区和应用程序。

(2)有足够大的磁盘或磁盘阵列等设备存放数据库,有足够大的磁带(或光盘)作数据备份。

(3)要求系统有较高的通道能力,以提高数据传送率。

2.软件

数据库系统的软件主要包括:

(1)数据库管理系统。数据库管理系统是为数据库的建立、使用和维护配置的系统软件。

(2)支持数据库管理系统运行的操作系统。

(3)具有与数据库接口的高级语言及其编译系统,便于开发应用程序。

(4)以数据库管理系统为核心的应用开发工具。应用开发工具是系统为应用开发人员和最终用户提供的高效率、多功能的应用生成器、第四代语言等各种软件工具。它们为数据库系统的开发和应用提供了良好的环境。

(5)为特定应用环境开发的数据库应用系统。

3.人员

开发、管理和使用数据库系统的人员主要包括数据库管理员、系统分析员和数据库设计人员、应用程序员和最终用户。不同的人员涉及不同的数据抽象级别,具有不同的数据视图,如图1.17所示。这些人员分别包括如下职责。

《数据库系统概论》学习笔记_第2张图片

(1)数据库管理员

在数据库系统环境下有两类共享资源,一类是数据库,另一类是数据库管理系统软件。因此需要有专门的管理机构来监督和管理数据库系统。数据库管理员则是这个机构的一个(组)人员,负责全面管理和控制数据库系统。具体包括如下职责。

①决定数据库中的信息内容和结构。数据库中要存放哪些信息,数据库管理员要参与决策。因此,数据库管理员必须参加数据库设计的全过程,并与用户、应用程序员、系统分析员密切合作、共同协商,做好数据库设计。

②决定数据库的存储结构和存取策略。数据库管理员要综合各用户的应用要求,和数据库设计人员共同决定数据的存储结构和存取策略,以求获得较高的存取效率和存储空间利用率。

③定义数据的安全性要求和完整性约束条件。数据库管理员的重要职责是保证数据库的安全性和完整性。因此,数据库管理员负责确定各个用户对数据库的存取权限、数据的保密级别和完整性约束条件。

④监控数据库的使用和运行。数据库管理员还有一个重要职责就是监视数据库系统的运行情况,及时处理运行过程中出现的问题。比如系统发生各种故障时,数据库会因此遭到不同程度的破坏,数据库管理员必须在最短时间内将数据库恢复到正确状态,并尽可能不影响或少影响计算机系统其他部分的正常运行。为此,数据库管理员要定义和实施适当的后备和恢复策略,如周期性的转储数据、维护日志文件等。

⑤数据库的改进和重组、重构。数据库管理员还负责在系统运行期间监视系统的空间利用率、处理效率等性能指标,对运行情况进行记录、统计分析,依靠工作实践并根据实际应用环境不断改进数据库设计。不少数据库产品都提供了对数据库运行状况进行监视和分析的工具,数据库管理员可以使用这些软件完成这项工作。

另外,在数据运行过程中,大量数据不断插入、删除、修改,时间一长,数据的组织结构会受到严重影响,从而降低系统性能。因此,数据库管理员要定期对数据库进行重组织,以改善系统性能。当用户的需求增加和改变时,数据库管理员还要对数据库进行较大的改造,包括修改部分设计,即数据库的重构。

(2)系统分析员和数据库设计人员

系统分析员负责应用系统的需求分析和规范说明,要和用户及数据库管理员相结合,确定系统的硬件软件配置,并参与数据库系统的概要设计。

数据库设计人员负责数据库中数据的确定及数据库各级模式的设计。数据库设计人员必须参加用户需求调查和系统分析,然后进行数据库设计。在很多情况下,数据库设计人员就由数据库管理员担任。

(3)应用程序员

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

(4)用户

这里用户是指最终用户(end user)。最终用户通过应用系统的用户接口使用数据库。常用的接口方式有浏览器、菜单驱动、表格操作、图形显示、报表书写等。

最终用户可以分为如下三类。

①偶然用户。这类用户不经常访问数据库,但每次访问数据库时往往需要不同的数据库信息,这类用户一般是企业或组织机构的高中级管理人员。

②简单用户。数据库的多数最终用户都是简单用户,其主要工作是查询和更新数据库,一般都是通过应用程序员精心设计并具有友好界面的应用程序存取数据库。银行的职员、航空公司的机票预订工作人员、宾馆总台服务员等都属于这类用户。

③复杂用户。复杂用户包括工程师、科学家、经济学家、科学技术工作者等具有较高科学技术背景的人员。这类用户一般都比较熟悉数据库管理系统的各种功能,能够直接使用数据库语言访问数据库,甚至能够基于数据库管理系统的应用程序接口编制自己的应用程序。

第2章 关系数据库

本章系统讲解关系数据库的重要概念,包括关系模型和关系代数。

本书第2~6章、第8章和第9章将集中讨论关系数据库的有关问题。其中,第2章讲解关系模型的基本概念,即关系模型的数据结构、关系操作和关系的完整性:第3、4、5章介绍关系数据库标准语言SQL的数据定义、数据查询、数据更新、数据安全性和完整性控制等功能:第6章介绍关系数据理论,这是关系数据库的理论基础,也是关系数据库系统逻辑设计的工具;第8章介绍如何通过编程方法对关系数据库进行操纵;第9章讲解关系数据库查询处理和查询优化。

按照数据模型的三个要素,关系模型由关系数据结构、关系操作集合和关系完整性约束三部分组成。下面将对这三部分内容进行分别介绍。其中2.1节讲解关系数据结构,包括关系的形式化定义及有关概念; 2.2节讲解关系操作;2.3节讲解关系的三类完整性约束;2.4节讲解关系代数,这是关系数据库系统中实现关系操作的一种语言;最后,在2.5节介绍关系演算。

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

2.1.1 关系

关系模型的数据结构非常简单,只包含单一的数据结构——关系。在用户看来,关系模型中数据的逻辑结构是一张扁平的二维表。

关系模型的数据结构描述出了现实世界的实体以及实体间的各种联系。也就是说,在关系模型中,现实世界的实体以及实体间的各种联系均用单一的结构模型,即关系来显示。

1.域(domain)

定义2.1 域是一组具有相同数据类型的值的集合。

2.笛卡尔积

笛卡尔积是域上的一种集合运算。

定义2.2 给定一组域D1, D2, .., Dn,允许其中某些域是相同的,这些域的笛卡尔积为

D1×D2×...×Dn = {(d1, d2, ..., dn)| di ∈ Di,i = 1,2,...,n }

其中,每一个元素(d1, d2, ..., dn)叫做一个n元组,或简称元组。元素中的每一个值di叫做一个分量。

一个域允许的不同取值个数称为这个域的基数。

若Di(i = 1,2,...,n)为有限集,其基数为mi(i = 1,2,...,n),则D1×D2×...×Dn的基数M为

M = ∏(n,i = 1)mi.

笛卡尔积可表示为一张二维表。表中的每行对应一个元组,表中的每一列的值来自一个域。

3.关系

定义2.3 D1×D2×...×Dn的子集叫做在域D1, D2, .., Dn上的关系,表示为R(D1, D2, .., Dn)。

这里R表示关系的名字,n是关系的目或度。

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

当n=1时,称该关系为单元关系(unary relation),或一元关系。当n=2时,称该关系为二元关系(binary relation)。

关系是笛卡儿积的有限子集,所以关系也是一张二维表,表的每行对应一个元组,表的每列对应一个域。由于域可以相同,为了加以区分,必须对每列起一个名字,称为属性(attribute)。n目关系必有n个属性。

若关系中的某一属性组的值能唯一地标识一个元组,而其子集不能,则称该属性组为候选码(candidate key)。

若一个关系有多个候选码,则选定其中一一个 为主码( primary key)。

候选码的诸属性称为主属性(prime attribute)。不包含在任何候选码中的属性称为非主属性(non-prime attribute)或非码属性(non-key attribute)。

在最简单的情况下,候选码只包含一个属性。在最极端的情况下,关系模式的所有属性是这个关系模式的候选码,称为全码(all-key)。

一般来说,D1, D2, .. Dn的笛卡儿积是没有实际语义的,只有它的某个真子集才有实际含义。

关系可以有三种类型:基本关系(通常又称为基本表或基表)、查询表和视图表。其中,基本表是实际存在的表,它是实际存储数据的逻辑表示;查询表是查询结果对应的表;视图表是由基本表或其他视图表导出的表,是虚表,不对应实际存储的数据。

按照定义2.2,关系可以是一个无限集合。由于组成笛卡儿积的域不满足交换律,所以按照数学定义,(d1, d2, .. dn)≠(d2, d1, ...,dn)。当关系作为关系数据模型的数据结构时,需要给予如下的限定和扩充。

(1)无限关系在数据库系统中是无意义的。因此,限定关系数据模型中的关系必须是有限集合。

(2)通过为关系的每个列附加一个属性名的方法取消关系属性的有序性,即(d1, d2,..,di, dj, .. dn)= (d1, d2,..,dj, di, .. dn)(i, j=1, 2, ... n)。

因此,基本关系具有以下6条性质。

(1)列是同质的(homogeneous),即每一列中的分量是同一类型的数据,来自同一个域。

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

(3)列的顺序无所谓,即列的次序可以任意交换。由于列顺序是无关紧要的,因此在许多实际关系数据库产品中增加新属性时,永远是插至最后一列。

(4)任意两个元组的候选码不能取相同的值。

(5)行的顺序无所谓,即行的次序可以任意交换。

(6)分量必须取原子值,即每一个分量都必须是不可分的数据项。

关系模型要求关系必须是规范化(normalization)的,即要求关系必须满足一定的规范条件。这些规范条件中最基本的一条就是,关系的每一个分量必须是一个不可分的数据项。规范化的关系简称为范式(Normal Form, NF)。

注意:在许多实际关系数据库产品中,基本表并不完全具有这6条性质。例如,有的数据库产品仍然区分了属性顺序和元组的顺序。许多时候人们把元组称为记录,元组和记录是同一个概念。

2.1.2 关系模式

定义2.4 关系的描述称为 关系模式(relation schema)。它可以形式化地表示为

R(U, D, DOM, F),

其中R为关系名,U为组成该关系的属性名集合,D为U中属性所来自的域,DOM为属性向域的映像集合,F为属性间数据的依赖关系集合。

属性间的数据依赖将在第6章讨论,本章中关系模式仅涉及关系名、各属性名、域名、属性向域的映像共4部分,即R(U, D, DOM)。

例如,在上面例子中,由于导师和研究生出自同一个域——人,所以要取不同的属性名,并在模式中定义属性向域的映像,即说明它们分别出自哪个域。

关系模式通常可以简记为R(U)或R(A1, A2,…,An),其中R为关系名,A1, A2,…,An为属性名。而域名及属性向域的映像常常直接说明为属性的类型、长度。

关系是关系模式在某一时刻的状态或内容。关系模式是静态的、稳定的,而关系是动态的、随时间不断变化的,因为关系操作在不断地更新着数据库中的数据。例如,学生关系模式在不同的学年,学生关系是不同的。在实际工作中,人们常常把关系模式和关系都笼统地称为关系,这不难从上下文中加以区别,希望读者注意。

2.1.3 关系数据库

在关系模型中,实体以及实体间的联系都是用关系来表示的。例如导师实体、研究生实体、导师与研究生之间的一对多联系都可以分别用一个关系来表示。在一个给定的应用领域中,所有关系的集合构成一个关系数据库。

关系数据库也有型和值之分。关系数据库的型也称为关系数据库模式,是对关系数据库的描述。关系数据库模式包括若干域的定义,以及在这些域上定义的若干关系模式。

关系数据库的值是这些关系模式在某一时刻对应的关系的集合,通常就称为关系数据库。

2.1.4 关系模型的存储结构

我们已经知道,在关系数据模型中实体及实体间的联系都用表来表示,但表是关系数据的逻辑模型。在关系数据库的物理组织中,有的关系数据库管理系统中一个表对应一个操作系统文件,将物理数据组织交给操作系统完成;有的关系数据库管理系统从操作系统那里申请若干个大的文件,自己划分文件空间,组织表、索引等存储结构,并进行存储管理。

2.2 关系操作

2.2.1 基本的关系操作

关系模型中常用的关系操作包括查询(query)操作和插入(insert)、删除(delete)、修改操作两大部分。

关系的查询表达能力很强,是关系操作中最主要的部分。查询操作又可以分为选择(select)、投影(project)、连接(join)、除(divide)、并(union)、差(except)、交(intersection)、笛卡儿积等。其中选择、投影、并、差、笛卡儿积是5种基本操作,其他操作可以用基本操作来定义和导出,就像乘法可以用加法来定义和导出一样。

关系操作的特点是集合操作方式,即操作的对象和结果都是集合。这种操作方式也称为一次一集合(set-at-a-time) 的方式。相应地,非关系数据模型的数据操作方式则为一次一记录(record-at-a-time) 的方式。

2.2.2 关系数据语言的分类

早期的关系操作能力通常用代数方式或逻辑方式来表示,分别称为关系代数(relationalalgebra)和关系演算(relational calculus)。 关系代数用对关系的运算来表达查询要求,关系演算则用谓词来表达查询要求。关系演算又可按谓词变元的基本对象是元组变量还是域变量分为元组关系演算和域关系演算。一个关系数据语言能够表示关系代数可以表示的查询,称为具有完备的表达能力,简称关系完备性。已经证明关系代数、元组关系演算和域关系演算三种语言在表达能力上是等价的,都具有完备的表达能力。

关系代数、元组关系演算和域关系演算均是抽象的查询语言,这些抽象的语言与具体的关系数据库管理系统中实现的实际语言并不完全样。 但它们能用作评估实际系统中查询语言能力的标准或基础。实际的查询语言除了提供关系代数或关系演算的功能外,还提供了许多附加功能,例如聚集函数(aggregation function)、 关系赋值、算术运算等,使得目前实际查询语言的功能十分强大。

另外,还有一种介于关系代数和关系演算之间的结构化查询语言(Structured QueryLanguage, SQL)。 SQL不仅具有丰富的查询功能,而且具有数据定义和数据控制功能,是集查询、数据定义语言、数据操纵语言和数据控制语言(Data Control Language, DCL)于一体的关系数据语言。它充分体现了关系数据语言的特点和优点,是关系数据库的标准语言。

因此,关系数据语言可以分为三类:

《数据库系统概论》学习笔记_第3张图片

特别地,SQL语言是一种高度非过程化的语言,用户不必请求数据库管理员为其建立特殊的存取路径,存取路径的选择由关系数据库管理系统的优化机制来完成。例如,在一个存储有几百万条记录的关系中查找符合条件的某一个或某一些记录,从原理上讲可以有多种查找方法。例如,可以顺序扫描这个关系,也可以通过某一种索引来查找。不同的查找路径(或者称为存取路径)的效率是不同的,有的完成某一个查询可能很快,有的可能极慢。关系数据库管理系统中研究和开发了查询优化方法,系统可以自动选择较优的存取路径,提高查询效率。

2.3 关系的完整性

关系模型的完整性规则是对关系的某种约束条件。也就是说,关系的值随着时间变化应该满足一些约束条件。这些约束条件实际上是现实世界的要求。任何关系在任何时刻都要满足这些语义约束。

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

2.3.1 实体完整性

关系数据库中每个元组应该是可区分的,是唯一的。这样的约束条件用实体完整性来保证。

规则2.1 实体完整性规则 若属性 (指一个或一组属性) A是基本关系R的主属性,则A不能取空值(null value)。所谓空值就是“不知道"或“不存在”或“无意义”的值。

例如,学生(学号,姓名,性别,专业号,年龄)关系中学号为主码,则学号不能取空值。

按照实体完整性规则的规定,如果主码由若干属性组成,则所有这些主属性都不能取空值。例如选修(学号,课程号,成绩)关系中,“学号、课程号”为主码,则“学号”和“课程号”两个属性都不能取空值。

对于实体完整性规则说明如下:

(1)实体完整性规则是针对基本关系而言的。一个基本表通常对应现实世界的一个实体集。例如学生关系对应于学生的集合。

(2)现实世界中的实体是可区分的,即它们具有某种唯一性标识。例如每个学生都是独立的个体,是不一样的。

(3)相应地,关系模型中以主码作为唯性标识。

(4)主码中的属性即主属性不能取空值。如果主属性取空值,就说明存在某个不可标识的实体,即存在不可区分的实体,这与第(2)点相矛盾,因此这个规则称为实体完整性。

2.3.2 参照完整性

现实世界中的实体之间往往存在某种联系,在关系模型中实体及实体间的联系都是用关系来描述的,这样就自然存在着关系与关系间的引用。先来看三个例子。

这三个例子说明关系与关系之间存在着相互引用、相互约束的情况。下面先引入外码的概念,然后给出表达关系之间相互引用约束的参照完整性的定义。

定义2.5 设F 是基本关系R的一个或一组属性,但不是关系R的码,Ks是基本关系S的主码。如果F与Ks相对应,则称F是R的外码(foreign key), 并称基本关系R为参照关系(referencing relation),基本关系S为被参照关系(referenced relation)或目标关系(target relation)。关系R和S不一定是不同的关系。

《数据库系统概论》学习笔记_第4张图片

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

在例2.1中,学生关系的“专业号”属性与专业关系的主码“专业号”相对应,因此“专业号”属性是学生关系的外码。这里专业关系是被参照关系,学生关系为参照关系。

在例2.2中,选修关系的“学号”属性与学生关系的主码“学号”相对应:选修关系“课程号”属性与课程关系的主码“课程号”相对应,因此“学号”和“课程号”属性是选修关系的外码。这里学生关系和课程关系均为被参照关系,选修关系为参照关系。

在例2.3中,“班长”属性与本身的主码“学号”属性相对应,因此“班长”是外码。这里,学生关系既是参照关系也是被参照关系。

需要指出的是,外码并不一定要与相应的主码同名,如例2.3中学生关系的主码为学号,外码为班长。不过,在实际应用中为了便于识别,当外码与相应的主码属于不同关系时,往往给它们取相同的名字。

参照完整性规则就是定义外码与主码之间的引用规则。

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

●或者取空值(F 的每个属性值均为空值);

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

例如,对于例2.1,学生关系中每个元组的“专业号”属性只能取下面两类值:

●空值,表示尚未给该学生分配专业;

●非空值,这时该值必须是专业关系中某个元组的“专业号”值,表示该学生不可能分配到一个不存在的专业中。即被参照关系“专业”中一定存在一个元组,它的主码值等于该参照关系“学生”中的外码值。

参照完整性规则中,R与S可以是同一个关系。例如对于例2.3,按照参照完整性规则,“班长”属性值可以取两类值:

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

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

2.3.3 用户定义的完整性

任何关系数据库系统都应该支持实体完整性和参照完整性。这是关系模型所要求的。除此之外,不同的关系数据库系统根据其应用环境的不同,往往还需要一些特殊的约束条件。用户定义的完整性就是针对某一具体关系数据库的约束条件,它反映某一具体应用所涉及的数据必须满足的语义要求。例如某个属性必须取唯一值、某个非主属性不能取空值等。例如,在例2.1的学生关系中,若按照应用的要求学生不能没有姓名,则可以定义学生姓名不能取空值;某个属性(如学生的成绩),的取值范围可以定义在0~ 100之间等。

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

在早期的关系数据库管理系统中没有提供定义和检验这些完整性的机制,因此需要应用开发人员在应用系统的程序中进行检查。例如在例2.2的选修关系中,每插入一条记录,必须在应用程序中写一段程序来检查其中的学号是否等于学生关系中的某个学号,并检查其中的课程号是否等于课程关系中的某个课程号。如果等于,则插入这一条选修记录,否则就拒绝插入,并给出错误信息。

2.4 关系代数

关系代数是一种抽象的查询语言,它用对关系的运算来表达查询。

任何一种运算都是将一定的运算符作用于一定的运算对象上,得到预期的运算结果。所以运算对象、运算符、运算结果是运算的三大要素。

关系代数的运算对象是关系,运算结果亦为关系。关系代数用到的运算符包括两类:集合运算符和专门的关系运算符,如表2.4所示。

《数据库系统概论》学习笔记_第5张图片

关系代数的运算按运算符的不同可分为传统的集合运算和专门的关系运算两类。其中,传统的集合运算将关系看成元组的集合,其运算是从关系的“水平”方向,即行的角度来进行;而专门的关系运算不仅涉及行,而且涉及列。比较运算符和逻辑运算符是用来辅助专门的关系运算符进行操作的。

2.4.1 传统的集合运算

传统的集合运算是二目运算,包括并、差、交、笛卡儿积4种运算。

设关系R和关系S具有相同的目n(即两个关系都有n个属性),且相应的属性取自同一个域,t 是元组变量,t∈R表示t是R的一个元组。

可以定义并、 差、交、笛卡儿积运算如下。

(1)并(union)

关系R与关系S的并记作

R∪S={tIt∈R V t∈S}

其结果仍为n目关系,由属于R或属于S的元组组成。

(2)差(except)

关系R与关系S的差记作

R-S={tIt∈R∧t∉S}

其结果关系仍为n目关系,由属于R而不属于S的所有元组组成。

(3) 交(intersection)

关系R与关系S的交记作

R∩S={t|t∈R∧t∈S}

其结果关系仍为n目关系,由既属于R又属于S的元组组成。关系的交可以用差来表示,即R∩S=R-(R-S)。

(4)笛卡儿积(cartesian product)

这里的笛卡儿积严格地讲应该是广义的笛卡儿积(extended cartesian product),因为这里笛卡儿积的元素是元组。

两个分别为n目和m目的关系R和S的笛卡儿积是一个(n+m)列的元组的集合。元组的前n列是关系R的一个元组,后m列是关系S的一个元组。若R有k1个元组,S有k2个元组,则关系R和关系S的笛卡儿积有k1×k2个元组。记作

R×S= {tr⌒ts|tr∈R∧ts∈S}.

2.4.2 专门的关系运算

专门的关系运算包括选择、投影、连接、除运算等。为了叙述上的方便,先引入几个记号。

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

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

(3) R为n目关系,S为m目关系。tr∈R, ts∈S, tr⌒ts称为元组的连接(concatenation) 或元组的串接。它是一个n+m列的元组,前n个分量为R中的一个n元组,后m个分量为S中的一个m元组。

(4)给定一个关系R(X, Z), X和Z为属性组。当t[X]=x时,x在R中的象集(images set)定义为

Zx={t[z]|t∈R, t[X]=x}

它表示R中属性组X上值为x的诸元组在Z上分量的集合。

下面给出这些专门的关系运算的定义。

1.选择

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

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

其中F表示选择条件,它是一个逻辑表达式,取逻辑值“真”或“假”。

逻辑表达式F的基本形式为X1θY1.

其中θ表示比较运算符,它可以是>,≥,<,≤, =或<。X1,Y1等是属性名,或为常量,或为简单函数;属性名也可以用它的序号来代替。在基本的选择条件上可以进一步进行逻辑运算,即进行求非()、与(∧)、或(∨)运算。条件表达式中的运算符如表2.5所示。

《数据库系统概论》学习笔记_第6张图片

选择运算实际上是从关系R中选取使逻辑表达式F为真的元组。这是从行的角度进行的运算。

2.投影(projection)

关系R上的投影是从R中选择出若干属性列组成新的关系。记作

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

其中A为R中的属性列。

投影操作是从列的角度进行的运算。

投影之后不仅取消了原关系中的某些列,而且还可能取消某些元组,因为取消了某些属性列后,就可能出现重复行,应取消这些完全相同的行。

3.连接(join)

连接也称为θ连接。它是从两个关系的笛卡儿积中选取属性间满足一定条件的元组。记作

其中,A和B分别为R和S上列数相等且可比的属性组,θ是比较运算符。连接运算从R和S的笛卡儿积R×S中选取R关系在A属性组上的值与S关系在B属性组上的值满足比较关系θ的元组。

连接运算中有两种最为重要也最为常用的连接,一种是等值连接(equijoin), 另一种是自然连接(natural join)。

θ为“=”的连接运算称为等值连接。它是从关系R与S的广义笛卡儿积中选取A、B属性值相等的那些元组,即等值连接为

自然连接是一种特殊的等值连接。它要求两个关系中进行比较的分量必须是同名的属性组,并且在结果中把重复的属性列去掉。即若R和S中具有相同的属性组B, U为R和S的全体属性集合,则自然连接可记作

一般的连接操作是从行的角度进行运算,但自然连接还需要取消重复列,所以是同时从行和列的角度进行运算。

两个关系R和S在做自然连接时,选择两个关系在公共属性上值相等的元组构成新的关系。此时,关系R中某些元组有可能在S中不存在公共属性上值相等的元组,从而造成R中这些元组在操作时被舍弃了,同样,S中某些元组也可能被舍弃。这些被舍弃的元组称为悬浮元组(dangling tuple)。 例如,在图2.7(e)的自然连接中,R中的第4个元组,S中的第5个元组都是被舍弃掉的悬浮元组。

如果把悬浮元组也保存在结果关系中,而在其他属性上填空值(NULL),那么这种连接就叫做外连接(outer join);如果只保留左边关系R中的悬浮元组就叫做左外连接(left outer join或left join);如果只保留右边关系S中的悬浮元组就叫做右外连接(right outer join或right join)。

4.除运算(division)

设关系R除以关系S的结果为关系T,则T包含所有在R但不在S中的属性及其值,且T的元组与S的元组的所有组合都在R中。

下面用象集来定义除法:

给定关系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上投影的集合。记作

其中Yx为x在R中的象集,x=tr[x]。

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

本节介绍了8种关系代数运算,其中并、差、笛卡儿积、选择和投影这5种运算为基本的运算。其他三种运算,即交、连接和除,均可以用这5种基本运算来表达。引进它们并不增加语言的能力,但可以简化表达。

关系代数中,这些运算经有限次复合后形成的表达式称为关系代数表达式。

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

第3章系统而详尽地讲解了SQL的数据定义、数据查询和数据更新三部分功能,并进一步讲述关系数据库的基本概念。

结构化查询语言(Structured Query Language, SQL)是关系数据库的标准语言,也是一个通用的、功能极强的关系数据库语言。其功能不仅仅是查询,而是包括数据库模式创建、数据库数据的插入与修改、数据库安全性完整性定义与控制等一系列功能。

3.1 SQL概述

3.1.1 SQL的产生与发展

目前,没有一个数据库系统能够支持SQL标准的所有概念和特性。大部分数据库系统能支持SQL/92标准中的大部分功能以及SQL99、SQL2003中的部分新概念。同时,许多软件厂商对SQL基本命令集还进行了不同程度的扩充和修改,又可以支持标准以外的一些功能特性。

3.1.2 SQL的特点

SQL集数据查询、数据操纵、数据定义和数据控制功能于一体,其主要特点包括以下几部分。

1.综合统一

数据库系统的主要功能是通过数据库支持的数据语言来实现的。

非关系模型(层次模型、网状模型)的数据语言一般都分为:

(1)模式数据定义语言(模式DDL)。

(2)外模式数据定义语言(外模式DDL或子模式DDL)。

(3)数据存储有关的描述语言(DSDL)。

(4)数据操纵语言(DML)。

它们分别用于定义模式、外模式、内模式和进行数据的存取与处置。当用户数据库投入运行后,如果需要修改模式,必须停止现有数据库的运行,转储数据,修改模式并编译后再重装数据库,十分麻烦。

SQL集数据定义语言、数据操纵语言、数据控制语言的功能于一体,语言风格统一,可以独立完成数据库生命周期中的全部活动,包括以下一系列操作要求:

· 定义和修改、删除关系模式,定义和删除视图,插入数据,建立数据库。

· 对数据库中的数据进行查询和更新。

· 数据库重构和维护。

· 数据库安全性、完整性控制,以及事务控制。

· 嵌入式SQL和动态SQL定义。

这就为数据库应用系统的开发提供了良好的环境。特别是用户在数据库系统投入运行后还可根据需要随时地、逐步地修改模式,并不影响数据库的运行,从而使系统具有良好的可扩展性。

另外,在关系模型中实体和实体间的联系均用关系表示,这种数据结构的单一性带来了数据操作符的统一性,查找、插入、删除、更新等每一种操作都只需一种操作符,从而克服了非关系系统由于信息表示方式的多样性带来的操作复杂性。

2.高度非过程化

非关系数据模型的数据操纵语言是“面向过程”的语言,用“过程化”语言完成某项请求必须指定存取路径。而用SQL进行数据操作时,只要提出“做什么”,而无须指明“怎么做”,因此无须了解存取路径。存取路径的选择以及SQL的操作过程由系统自动完成。这不但大大减轻了用户负担,而且有利于提高数据独立性。

3.面向集合的操作方式

非关系数据模型采用的是面向记录的操作方式,操作对象是一条记录。例如查询所有平均成绩在80分以上的学生姓名,用户必须一条一条地把满足条件的学生记录找出来(通常要说明具体处理过程,即按照哪条路径,如何循环等)。而SQL采用集合操作方式,不仅操作对象、查找结果可以是元组的集合,而且一次插入、删除、更新操作的对象也可以是元组的集合。

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

SQL既是独立的语言,又是嵌入式语言。作为独立的语言,它能够独立地用于联机交互的使用方式,用户可以在终端键盘上直接键入SQL命令对数据库进行操作:作为嵌入式语言,SQL语句能够嵌入到高级语言(例如C、C++、Java)程序中,供程序员设计程序时使用。而在两种不同的使用方式下,SQL的语法结构基本上是一致的。这种以统一的语法结构提供多种不同使用方式的做法,提供了极大的灵活性与方便性。

5.语言简洁,易学易用

SQL功能极强,但由于设计巧妙,语言十分简洁,完成核心功能只用了9个动词,如表3.2所示。SQL接近英语口语,因此易于学习和使用。

《数据库系统概论》学习笔记_第7张图片

3.1.3 SQL的基本概念

支持SQL的关系数据库管理系统同样支持关系数据库三级模式结构。其中外模式包括若干视图(view)和部分基本表(base table),数据库模式包括若干基本表,内模式包括若干存储文件(stored file)。

《数据库系统概论》学习笔记_第8张图片

用户可以用SQL对基本表和视图进行查询或其他操作。基本表和视图一样,都是关系。

基本表是本身独立存在的表,在关系数据库管理系统中,一个关系就对应一个基本表。一个或多个基本表对应一个存储文件,一个表可以带若干索引,索引也存放在存储文件中。

存储文件的逻辑结构组成了关系数据库的内模式。存储文件的物理结构对最终用户是隐蔽的。

视图是从一个或几个基本表导出的表。它本身不独立存储在数据库中,即数据库中只存放视图的定义而不存放视图对应的数据。这些数据仍存放在导出视图的基本表中,因此视图是一个虚表。视图在概念上与基本表等同,用户可以在视图上再定义视图。

3.2 学生-课程数据库

本章以学生-课程数据库为例来讲解SQL的数据定义、数据操纵数据查询和数据控制语句。

为此,首先要定义一个学生-课程模式S-T。学生-课程数据库中包括以下三个表。

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

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

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

关系的主码加下划线表示。

3.3 数据定义

关系数据库系统支持三级模式结构,其模式、外模式和内模式中的基本对象有模式、表、视图和索引等。因此SQL的数据定义功能包括模式定义、表定义、视图和索引的定义,如表3.3所示。

表3.3 SQL的数据定义语句

操作对象

操作方式

创建

删除

修改

模式

CREATE SCHEMA

DROP SCHEMA

CREATE TABLE

DROP TABLE

ALTER TABLE

视图

CREATE VIEW

DROP VIEW

索引

CREATE INDEX

DROP INDEX

ALTER INDEX

SQL标准不提供修改模式定义和修改视图定义的操作。用户如果想修改这些对象,只能先将它们删除然后再重建。SQL标准也没有提供索引相关的语句,但为了提高查询效率,商用关系数据库管理系统通常都提供了索引机制和相关的语句,如表3.3中创建、删除和修改索引等。

在早期的数据库系统中,所有数据库对象都属于一个数据库,也就是说只有一个命名空间。现代的关系数据库管理系统提供了一个层次化的数据库对象命名机制,如图3.3所示。一个关系数据库管理系统的实例(instance)中可以建立多个数据库,一个数据库中可以建立多个模式,一个模式下通常包括多个表、视图和索引等数据库对象。

《数据库系统概论》学习笔记_第9张图片

3.3.1 模式的定义与删除

1.定义模式

在SQL中,模式定义语句如下:

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

如果没有指定<模式名>,那么<模式名>隐含为<用户名>。

要创建模式,调用该命令的用户必须拥有数据库管理员权限,或者获得了数据库管理员授予的CREATE SCHEMA的权限。

[例3.1] 为用户WANG定义一个学生-课程模式S-T。

CREATE SCHEMA "S-T" AUTHORIZATION WANG;

[例3.2] CREATE SCHEMA AUTHORIZATION WANG;

该语句没有指定 <模式名> ,所以 <模式名>隐含为用户名WANG。

定义模式实际上定义了一个命名空间,在这个空间中可以进一步定义该模式包含的数据库对象,如基本表、视图、索引等。这些数据库对象可以用表3.3中相对应的CREATE语句来定义。

目前,在CREATE SCHEMA中可以接受CREATE TABLE,CREATE VIEW和GRANT子句。也就是说,用户可以在创建模式的同时,在这个模式定义中进一步创建基本表、视图,定义授权。即

CREATE SCHEMA <模式名> AUTHORIZATION <用户名> [<表定义子句> | <视图定义子句> | <授 权定义子句>];

[例3.3] 为用户ZHANG创建一个模式TEST,并且在其中定义一个表TAB1。

CREATE SCHEMA TEST AUTHORIZATION ZHANG

CREATE TABLE TAB1(COL1 SMALLINT,

COL2 INT,

COL3 CHAR(20),

COL4 NUMERIC(10,3),

COL5 DECIMAL(5,2)

);

2.删除模式

在SQL中,删除模式语句如下:

DROP SCHEMA <模式名> ;

其中CASCADE和RESTRICT两者必选其一。选择了CASCADE(级联),表示在删除模式的同时把该模式中所有的数据库对象全部删除;选择了RESTRICT(限制),表示如果该模式中已经定义了下属的数据库对象(如表、视图等),则拒绝该删除语句的执行。只有当该模式中没有任何下属的对象时才能执行DROP SCHEMA语句。

[例3.4] DROP SCHEMA ZHANG CASCADE;

该语句删除了模式ZHANG,同时,该模式中已经定义的表TAB1也被删除了。

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

1.定义基本表

创建了一个模式就建立了一个数据库的命名空间,一个框架。在这个空间中首先要定义的是该模式包含的数据库基本表。

SQL语言使用CREATE TABLE语句定义基本表,其基本格式如下:

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

[,<列名><数据类型>[列级完整性约束条件]]

...

[,<表级完整性约束条件>]);

建表的同时通常还可以定义与该表有关的完整性约束条件,这些完整性约束条件被存入系统的数据字典中,当用户操作表中数据时,由关系数据库管理系统自动检查该操作是否违背这些完整性约束条件。如果完整性约束条件涉及该表的多个属性列,则必须定义在表级上,否则既可以定义在列级也可以定义在表级。

[例3.5] 建立一个“学生”表Student。

CREATE TABLE Student

(Sno CHAR(9) PRIMARY KEY, /*列级完整性约束条件,Sno是主码*/

Sname CHAR(20) UNIQUE, /*Sname取唯一值*/

Ssex CHAR(2),

Sage SMALLINT,

Sdept CHAR(20)

);

系统执行该CREATE TABLE语句后,就在数据库中建立一个新的空“学生”表Student,并将有关“学生”表的定义及有关约束条件存放在数据字典中。

[例3.6] 建立一个“课程”表Course。

CREATE TABLE Course

(Cno CHAR(4) PRIMARY KEY, /*列级完整性约束条件,Cno是主码*/

Cname CHAR(40) NOT NULL, /*列级完整性约束条件,Cname不能取空值*/

Cpno CHAR(4), /*Cpno的含义是先修课*/

Ccredit SMALLINT,

FOREIGN KEY (Cpno) REFERENCES Course(Cno)

/*表级完整性约束条件,Cpno是外码,被参照表是Course,被参照列是Cno*/

);

本例说明参照表和被参照表可以是同一个表。

[例3.7] 建立学生选课表SC。

CREATE TABLE SC

(Sno CHAR(9),

Cno CHAR(4),

Grade SMALLINT,

PRIMARY KEY(Sno, Cno), /*主码由两个属性构成,必须作为表级完整性进行定义*/

FOREIGN KEY(Sno) REFERENCES Student(Sno),

/*表级完整性约束条件,Sno是外码,被参照表是Student,被参照列是Sno*/

FOREIGN KEY(Cno) REFERENCES Course(Cno)

/*表级完整性约束条件,Cno是外码,被参照表是Course,被参照列是Cno*/

);

2.数据类型

关系模型中一个很重要的概念是域。每一个类型来自一个域,它的取值必须是域中的值。

在SQL中域的概念用数据类型来实现。定义表的各个属性时需要指明其数据类型及长度。SQL标准支持多种数据类型,表3.4列出了几种常用数据类型。要注意,不同的关系数据库管理系统中支持的数据类型不完全相同。

表3.4 数据类型

数据类型

含义

CHAR(n), CHARACTER(n)

长度为n的定长字符串

VARCHAR(n), CHARACTERVARYING(n)

最大长度为n的变长字符串

CLOB

字符串大对象

BLOB

二进制大对象

INT, INTEGER

长整数(4字节)

SMALLINT

短整数(2字节)

BIGINT

大整数(8字节)

NUMERIC(p, d)

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

DECIMAL(p, d),DEC(p, d)

同NUMERIC

REAL

取决于机器精度的单精度浮点数

DOUBLE PRECISION

取决于机器精度的双精度浮点数

FLOAT(n)

可选精度的浮点数,精度至少为n位数字

BOOLEAN

逻辑布尔量

DATE

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

TIME

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

TIMESTAMP

时间戳类型

INTERVAL

时间间隔类型

一个属性选用哪种数据类型要根据实际情况来决定,一般要从两个方面来考虑,一是取值范围,二是要做哪些运算。例如,对于年龄(Sage)属性,可以采用CHAR(3)作为数据类型,但考虑到要在年龄上做算术运算(如求平均年龄),所以要采用整数作为数据类型,因为在CHAR(n)数据类型上不能进行算术运算。整数又有长整数和短整数两种,因为一个人的年龄在百岁左右,所以选用短整数作为年龄的数据类型。

3.模式与表

每一个基本表都属于某一个模式,一个模式包含多个基本表。当定义基本表时一般可以有三种方法定义它所属的模式。例如在例3.1中定义了一个学生-课程模式S-T。现在要在S-T中定义Student、Course、SC等基本表。

方法一,在表名中明显地给出模式名。

CREATE TABLE "S-T".Student(···); /*Student所属的模式是S-T*/

CREATE TABLE "S-T".Course(···); /*Course所属的模式是S-T*/

CREATE TABLE "S-T".SC(···); /*SC所属的模式是S-T*/

方法二,在创建模式语句中同时创建表,如例3.3所示。

方法三,设置所属的模式,这样在创建表时表名中不必给出模式名。

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

搜索路径包含一组模式列表,关系数据库管理系统会使用模式列表中第一个存在的模式作为数据库对象的模式名。若搜索路径中的模式名都不存在,系统将给出错误。

使用下面的语句可以显示当前的搜索路径:

SHOW search_path;

搜索路径的当前默认值是$user, PUBLIC。其含义是首先搜索与用户名相同的模式名,如果该模式名不存在,则使用PUBLIC模式。

数据库管理员也可以设置搜索路径,例如:

SET search_path TO "S-T", PUBLIC;

然后,定义基本表:

CREATE TABLE Student(···);

实际结果是建立了S-T.Student基本表。因为关系数据库管理系统发现搜索路径中第一个模式名S-T存在,就把该模式作为基本表Student所属的模式。

4.修改基本表

随着应用环境和应用需求的变化,有时需要修改已经建立好的基本表。SQL语言用ALTER TABLE语句修改基本表,其一般格式为:

ALTER TABLE <表名>

[ADD [COLUMN] <新列名><数据类型> [完整性约束]]

[ADD<表级完整性约束>]

[DROP [COLUMN] <列名> [CASCADE|RESTRICT]]

[DROP CONSTRAINT <完整性约束名> [RESTRICT|CASCADE]]

[ALTER COLUMN <列名><数据类型>]

其中<表名>是要修改的基本表,ADD子句用于增加新列、新的列级完整性约束条件和新的表级完整性约束条件。DROP COLUMN子句用于删除表中的列,如果指定了CASCADE短语,则自动删除引用了该列的其他对象,比如视图;如果指定了RESTRICT短语,则如果该列被其他对象引用,RDBMS将拒绝删除该列。DROP CONSTRAINT子句用于删除指定的完整性约束条件。ALTER COLUMN子句用于修改原有的列定义,包括修改列名和数据类型。

【例3.8】 向Student表增加“入学时间”列,其数据类型为日期型。

ALTER TABLE Student ADD S_entrance DATE;

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

【例3.9】将年龄的数据类型由字符型(假设原来的数据类型是字符型)改为整数。

ALTER TABLE Student ALTER COLUMN Sage INT;

【例3.10】增加课程名称必须取唯一值的约束条件。

ALTER TABLE Course ADD UNIQUE(Cname);

5.删除基本表

当某个基本表不再需要时,可以用DROP TABLE语句删除它。其一般格式为:

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

若选择RESTRICT,则该表的删除是有限制条件的。欲删除的基本表不能被其他表的约束所引用(如CHECK,FOREIGN KEY等约束),不能有视图,不能有触发器(trigger),不能有存储过程或函数等。如果存在这些依赖该表的对象,则此表不能被删除。

若选择CASCADE,则该表的删除没有限制条件。在删除基本表的同时,相关的依赖对象,例如视图,都将一起被删除。

默认情况是RESTRICT。

【例3.11】删除Student表。

DROP TABLE Student CASCADE;

基本表定义一旦被删除,不仅表中的数据和此表的定义将被删除,而且此表上建立的索引、触发器等对象一般也都将被删除。有的关系数据库管理系统还会同时删除在此表上建立的视图。如果欲删除的基本表被其他基本表所引用,则这些表也可能被删除。例如SC表通过外码Sno引用Student,则执行例3.11后Student表被删除,SC也被级联删除。因此执行删除基本表的操作一定要格外小心。

【例3.12】 若表上建有视图,选择RESTRICT时表不能删除;选择CASCADE时可以删除表,视图也自动被删除。

CREATE VIEW IS_Student /*Student表上建立视图*/

AS

SELECT Sno,Sname,Sage

FROM Student

WHERE Sdept=‘IS’;

DROP TABLE Student RESTRICT; (会报错,存在依赖该表的对象(即上述视图),此表不能被删除)

DROP TABLE Student CASCADE; (系统返回提示,此表上的视图也被删除)

SELECT * FROM IS_Student;(报错:关系IS_Student不存在)

《数据库系统概论》学习笔记_第10张图片

“X”表示不能删除基本表,“√”表示能删除基本表,“保留”表示删除基本表后,还保留依赖对象。从比较表中可以知道:

(1)对于索引,删除基本表后,这三个关系数据库管理系统都自动删除该基本表上已经建立的所有索引。

(2)对于视图,Oracle 12c与SQL Server 2012是删除基本表后,还保留此基本表上的视图定义,但是已经失效。Kingbase ES分两种情况,若删除基本表时带RESTRICT选项,则不可以删除基本表;若删除基本表时带CASCADE选项,则可以删除基本表,同时也删除视图。Kingbase ES的这种策略符合SQL 2011标准。

(3)对于存储过程和函数,删除基本表后,这三个数据库产品都不自动删除建立在此基本表上的存储过程和函数,但是已经失效。

(4)如果欲删除的基本表上有触发器,或者被其他基本表的约束所引用(CHECK, FOREIGN KEY等),读者可以从比较表中得到这三个系统的处理策略,这里就不一一说明了。

同样,对于其他的SQL语句,不同的数据库产品在处理策略上会与标准有所差别。因此,如果发现本书中个别例子在某个数据库产品上不能通过时,请读者参见有关产品的用户手册,适当修改即可。

3.3.3 索引的建立与删除

当表的数据量比较大时,查询操作会比较耗时。建立索引是加快查询速度的有效手段。数据库索引类似于图书后面的索引,能快速定位到需要查询的内容。用户可以根据应用环境的需要在基本表上建立一个或多个索引,以提供多种存取路径,加快查找速度。

数据库索引有多种类型,常见索引包括顺序文件上的索引、B+树索引散列(hash)索引、位图索引等。顺序文件上的索引是针对按指定属性值升序或降序存储的关系,在该属性上建立一个顺序索引文件,索引文件由属性值和相应的元组指针组成。B+树索引是将索引属性组织成B+树形式,B+树的叶结点为属性值和相应的元组指针。B+树索引具有动态平衡的优点。散列索引是建立若干个桶,将索引属性按照其散列函数值映射到相应桶中,桶中存放索引属性值和相应的元组指针。散列索引具有查找速度快的特点。位图索引是用位向量记录索引属性中可能出现的值,每个位向量对应一个可能值。

索引虽然能够加速数据库查询,但需要占用一定的存储空间,当基本表更新时,索引要进行相应的维护,这些都会增加数据库的负担,因此要根据实际应用的需要有选择地创建索引。

目前SQL标准中没有涉及索引,但商用关系数据库管理系统一般都支持索引机制,只是不同的关系数据库管理系统支持的索引类型不尽相同。

一般说来, 建立与删除索引由数据库管理员或表的属主(owner), 即建立表的人,负责完成。关系数据库管理系统在执行查询时会自动选择合适的索引作为存取路径,用户不必也不能显式地选择索引。索引是关系数据库管理系统的内部实现技术,属于内模式的范畴。

1.建立索引

在SQL语言中,建立索引使用CREATE INDEX语句,其一般格式为

CREATE [UNIQUE][CLUSTER] INDEX <索引名>

ON <表名>(<列名>[<次序>][,<列名>[<次序>]]···);

其中,<表名>是要建索引的基本表的名字。索引可以建立在该表的一列或多列上,各列名之间用逗号分隔。每个<列名>后面还可以用<次序>制定索引值的排列次序,可选ASC(升序)或DESC(降序),默认值为ASC。

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

CLUSTER表示要建立的索引式聚簇索引。

【例3.13】为学生-课程数据库中的Student、Course和SC三个表建立索引。其中Student表按学号升序建立唯一索引,Course表按课程号升序建立唯一索引,SC表按学号升序和课程号降序建唯一索引。

CREATE UNIQUE INDEX Stusno ON Student(Sno);

CREATE UNIQUE INDEX Coucno ON Course(Cno);

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

2.修改索引

对于已经建立的索引,如果需要对其重新命名,可以使用ALTER INDEX语句。其一般格式为

ALTER INDEX <旧索引名> RENAME TO <新索引名>;

【例3.14】将SC表的SCno索引名改为SCSno。

ALTER INDEX SCno RENAME TO SCSno;

3.删除索引

索引一经建立就由系统使用和维护,不需用户干预。建立索引是为了减少查询操作的时间,但如果数据增、删、改频繁,系统会花费许多时间来维护索引,从而降低了查询效率。这时可以删除一些不必要的索引。

在SQL中,删除索引使用DROP INDEX语句,其一般格式为

DROP INDEX <索引名>;

【例3.15】删除Student表的Stusname索引。

DROP INDEX Stusname;

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

3.3.4 数据字典

数据字典是关系数据库管理系统内部的一组系统表,它记录了数据库中所有的定义信息,包括关系模式定义、视图定义、索引定义、完整性约束定义、各类用户对数据库的操作权限、统计信息等。关系数据库管理系统在执行SQL的数据定义语句时,实际上就是在更新数据字典表中的相应信息。在进行查询优化和查询处理时,数据字典中的信息是其重要依据。

3.4 数据查询

数据查询是数据库的核心操作。SQL提供了SELECT语句进行数据查询,该语句具有灵活的使用方式和丰富的功能。其一般格式为

SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]···

FROM <>[,<表名或视图名>···] | ()[AS]<别名>

[WHERE <条件表达式>]

[GROUP BY<列名1>[HAVING<条件表达式>]]

[ORDER BY<列名2>[ASC|DESC]];

整个SELECT语句的含义是,根据WHERE子句的条件表达式从FROM子句指定的基本表、视图或派生表中找出满足条件的元组,再按SELECT子句中的目标列表达式选出元组中的属性值形成结果表。

如果有GROUP BY子句,则将结果按<列名1>的值进行分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。如果GROUP BY子句带HAVING短语,则只有满足指定条件的组才予以输出。

如果有ORDER BY子句,则结果表还要按<列名2>的值的升序或降序排序。

SELECT语句既可以完成简单的单表查询,也可以完成复杂的连接查询和嵌套查询。

3.4.1 单表查询

单表查询是指仅涉及一个表的查询。

1.选择表中的若干列

选择表中的全部或部分列即关系代数的投影运算。

(1)查询指定列

在很多情况下,用户只对表中的一部分属性列感兴趣,这时可以通过在SELECT子句的<目标列表达式>中制定要查询的属性列。

【例3.16】查询全体学生的学号与姓名。

SELECT Sno,Sname

FROM Student;

该语句的执行过程可以是这样的:从Student表中取出一个元组,取出该元组在属性Sno和Sname上的值,形成一个新的元组作为输出。对Student表中的所有元组做相同的处理,最后形成一个结果关系作为输出。

【例3.17】查询全体学生的姓名、学号、所在系。

SELECT Sname, Sno, Sdept

FROM Student;

<目标列表达式>中各个列的先后顺序可以与表中的顺序不一致。用户可以根据应用的需要改变列的显示顺序。本例中先列出姓名,再列出学号和所在系。

(2)查询全部列

将表中的所有属性列都选出来有两种方法,一种方法就是在SELECT关键字后列出所有列名;如果列的显示顺序与其在基表中的顺序相同,也可以简单地将<目标列表达式>指定为*。

【例3.18】查询全体学生的详细记录。

SELECT *

FROM Student;

等价于

SELECT Sno,Sname,Ssex,Sage,Sdept

FROM Student;

(3)查询经过计算的值

SELECT子句的<目标列表达式>不仅可以是表中的属性列,也可以是表达式。

【例3.19】查询全体学生的姓名及其出生年份。

SELECT Sname,2014-Sage

FROM Student;

查询结果中第2列不是列名而是一个计算表达式,是用当时的年份减去学生的年龄。这样所得的即是学生的出生年份。

<目标列表达式>不仅可以是算术表达式,还可以是字符串常量、函数等。

【例3.20】查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名。

SELECT Sname,'Year of birth:',2014-Sage,LOWER(Sdept)

FROM Student;

用户可以通过指定别名来改变查询结果的列标题,这对于含算术表达式、常量、函数名的目标列表达式尤为有用。例如对例3.20可以定义如下列别名:

SELECT Sname NAME,'Year of birth:',BIRTH,2014-Sage BIRTHDAY

LOWER(Sdept) DEPARTMENT

FROM Student;

2.选择表中的若干元组

(1)消除取值重复的行

两个本来并不完全相同的元组在投影到指定的某些列上后,可能会变成相同的行。可以用DISTINCT消除它们。

【例3.21】查询选修了课程的学生学号。

SELECT Sno

FROM SC;

该查询结果里包含了许多重复的行。如果想去掉结果表中的重复行,必须指定DISDINCT:

SELECT DISTINCT Sno

FROM SC;

如果没有指定DISTINCT关键词,则默认为ALL,即保留结果表中取值重复的行。也就是说

SELECT Sno

FROM SC;

等价于

SELECT ALL Sno

FROM SC;

(2)查询满足条件的元组

查询满足指定条件的元组可以通过WHERE子句实现。WHERE子句常用的查询条件如表3.6所示。

表3.6 常用的查询条件

查询条件

谓词

比较

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

确定范围

BETWEEN AND, NOT BETWEEN AND

确定集合

IN, NOT IN

字符匹配

LIKE, NOT LIKE

空值

IS NULL, IS NOT NULL

多重条件(逻辑运算)

AND, OR, NOT

1)比较大小

用于进行比较的运算符一般包括=(等于),>(大于),<(小于),>=(大于等于),<=(小于等于), !=(不等于), <>(不等于), !>(不大于), !<(不小于)

【例3.22】查询计算机科学系全体学生的名单。

SELECT Sname

FROM Student

WHERE Sdept='CS';

关系数据库管理系统执行该查询的一种可能过程是:对Student表进行全表扫描,取出一个元组,检查该元组在Sdept列的值是否等于‘CS’,如果相等,则取出Sname列的值形成一个新的元组输出;否则跳过该元组,取下一个元组。重复该过程,直到处理完Student表的所有元组。

如果全校有数万个学生,计算机系的学生人数是全校学生的5%左右,可以在Student表的Sdept列上建立索引,系统会利用该索引找出Sdept='CS'的元组,从中取出Sname列值形成结果关系。这就避免了对Student表的全盘扫描,加快了查询速度。注意,如果学生较少,索引查找不一定能提高查询效率,系统仍会使用全表扫描。这由查询优化器按照某些规则或估计执行代价来作出选择。

【例3.23】查询所有年龄在20岁以下的学生姓名及其年龄。

SELECT Sname,Sage

FROM Student

WHERE Sage < 20;

【例3.24】查询考试成绩不合格的学生的学号。

SELECT DISTINCT Sno

FROM SC

WHERE Grade<60;

这里使用了DISTINCT短语,当一个学生有多门课程不及格,他的学号也只列一次。

2)确定范围

谓词BETWEEN···AND···和NOT BETWEEN···AND···可以用来查找属性值在(或不在)指定范围内的元组,其中BETWEEN后是范围的下限(即低值),AND后是范围的上限(即高值)。

【例3.25】查询年龄在20~23岁(包括20岁和23岁)之间的学生的姓名、系别和年龄。

SELECT Sname,Sdept,Sage

FROM Student

WHERE Sage BETWEEN 20 AND 23;

【例3.26】查询年龄不在20~23岁之间的学生姓名、系别和年龄。

SELECT Sname,Sdept,Sage

FROM Student

WHERE Sage NOT BETWEEN 20 AND 23;

3)确定集合

谓词IN可以用来查找属性值属于指定集合的元组。

【例3.27】查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。

SELECT Sname,Ssex

FROM Student

WHERE Sdept IN ('CS','MA','IS');

与IN相对的谓词是NOT IN,用于查找属性值不属于指定集合的元组。

【例3.28】查询既不是计算机科学系、数学系,也不是信息系的学生的姓名和性别。

SELECT Sname,Ssex

FROM Student

WHERE Sdept NOT IN ('CS','MA','IS');

4)字符匹配

谓词LIKE可以用来进行字符串的匹配。其一般语法格式如下:

[NOT] LIKE '<匹配串>' [ESCAPE'<换码字符>']

其含义是查找指定的属性列值与<匹配串>相匹配的元组。<匹配串>可以是一个完整的字符串,也可以含有通配符%和 _。其中:

  • %(百分号)代表任意长度(长度可以为0)的字符串。例如a%b表示以a开头,以b结尾的任意长度的字符串,如acb、addgb、ab等都满足该匹配串。

  • _(下横线)表示任意单个字符。例如a_b表示以a开头,以b结尾的长度为3的任意字符串。如acb、afb等都满足该匹配串。

【例3.29】查询学号为201215121的学生的详细情况。

SELECT *

FROM Student

WHERE Sno LIKE '201215121';

等价于

SELECT *

FROM Student

WHERE Sno='201215121';

如果LIKE后面的匹配串中不含通配符,则可以用=(等于)运算符取代LIKE谓词,用!=或<>(不等于)运算符取代NOT LIKE谓词。

【例3.30】查询所有姓刘的学生的姓名、学号和性别。

SELECT Sname,Sno,Ssex

FROM Student

WHERE Sname LIKE '刘%';

【例3.31】查询性“欧阳”且全名为三个汉字的学生的姓名。

SELECT Sname

FROM Student

WHERE Sname LIKE '欧阳_';

注意:数据库字符集为ASCII时一个汉字需要两个_;当字符集为GBK时只需要一个_。

【例3.32】查询名字中第二个字为“阳”的学生的姓名和学号。

SELECT Sname,Sno

FROM Student

WHERE Sname LIKE '_阳%';

【例3.33】查询所有不姓刘的学生的姓名、学号和性别。

SELECT Sname,Sno,Ssex

FROM Student

WHERE Sname NOT LIKE '刘%';

如果用户要查询的字符串本身就含有通配符%或_,这时就要使用ESCAPE '<换码字符>'短语对通配符进行转义了。

【例3.34】查询DB_Design课程的课程号和学分。

SELECT Cno,Ccredit

FROM Course

WHERE Cname LIKE 'DB\_Design' ESCAPE '\';

ESCAPE '\'表示“\”为换码字符。这样匹配串中紧跟在“\”后面的字符“_”不再具有通配符的含义,转义为普通的“_”字符。

【例3.35】查询以“DB_”为开头,且倒数第三个字符为i的课程的详细情况。

SELECT *

FROM Course

WHERE Cname LIKE 'DB\_%i_ _' ESCAPE '\';

这里的匹配串为'DB\_%i_ _'。第一个_前面有换码字符\,所以它被转义为普通的_字符。而i后面的两个_的前面均没有换码字符\,所以它们仍作为通配符。

5)涉及空值的查询

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

SELECT Sno,Cno

FROM SC

WHERE Grade IS NULL; /*分数Grade是空值*/

注意:这里的“IS”不能用等号(=)代替。

【例3.37】查所有有成绩的学生学号和课程号。

SELECT Sno,Cno

FROM SC

WHERE Grade IS NOT NULL;

6)多重条件查询

逻辑运算AND和OR可用来连接多个查询条件。AND的优先级高于OR,但用户可以用括号改变优先级。

【例3.38】查询计算机科学系年龄在20岁以下的学生姓名。

SELECT Sname

FROM Student

WHERE Sdept='CS' AND Sage<20;

在例3.27中的IN谓词实际上是多个OR运算符的缩写,因此该例中的查询也可以用OR运算符写成如下等价形式:

SELECT Sname,Ssex

FROM Student

WHERE Sdept='CS' OR Sdept='MA' OR Sdept='IS';

3.ORDER BY语句

用户可以用ORDER BY子句对查询结果按照一个或多个属性列的升序(ASC)或降序(DESC)排列,默认值为升序。

【例3.39】查询选修了3号课程的学生的学号及其成绩,查询结果按分数的降序排列。

SELECT Sno,Grade

FROM SC

WHERE Cno='3'

ORDER BY Grade DESC;

对于空值,排序时显示的次序由具体系统实现来决定。例如按升序排,含空值的元组最后显示;按降序排,空值的元组则最先显示。各个系统的实现可以不同,只要保持一致就行。

【例3.40】查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

SELECT *

FROM Student

ORDER BY Sdept,Sage DESC;

4.聚集函数

为了进一步方便用户,增强检索功能,SQL提供了许多聚集函数,主要有:

COUNT(*)

统计元组个数

COUNT( [DISTINCT|ALL]<列名>)

统计一列中值的个数

SUM([DISTINCT|ALL]<列名>)

计算一列值的总和(此列必须是数值型)

AVG([DISTINCT|ALL]<列名>)

计算一列值的平均值(此列必须是数值型)

MAX([DISTINCT|ALL]<列名>)

求一列值中的最大值

MIN([DISTINCT|ALL]<列名>)

求一列值中的最小值

如果指定DISTINCT短语,则表示在计算时要取消指定列中的重复值。如果不指定DISTINCT短语或指定ALL短语(ALL为默认值),则表示不取消重复值。

【例3.41】查询学生总人数。

SELECT COUNT(*)

FROM Student;

【例3.42】查询选修了课程的学生人数。

SELECT COUNT(DISTINCT Sno)

FROM SC;

学生每选修一门课,在SC中都有一条相应的记录。一个学生要选修多门课程,为避免重复计算学生人数,必须在COUNT函数中用DISTINCT短语。

【例3.43】计算选修1号课程的学生平均成绩。

SELECT AVG(Grade)

FROM SC

WHERE Cno='1';

【例3.44】查询选修1号课程的学生最高分数。

SELECT MAX(Grade)

FROM SC

WHERE Cno='1';

【例3.45】查询学生201215012选修课程的总学分数。

SELECT SUM(Ccredit)

FROM SC,Course

WHERE Sno='201215012' AND SC.Cno=Course.Cno;

当聚集函数遇到空值时,除COUNT(*)外,都跳过空值而只处理非空值。COUNT(*)是对元组进行计数,某个元组的一个或部分列取空值不影响COUNT的统计结果。

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

5.GROUP BY子句

GROUP BY子句将查询结果按某一列或多列的值分组,值相等的为一组。

对查询结果分组的目的是为了细化聚集函数的作用对象。如果未对查询结果分组,聚集函数将作用于整个查询结果,如前面的例3.41~3.45。分组后聚集函数将作用于每一个组,即每一组都有一个函数值。

【例3.46】求每个课程号及相应的选课人数。

SELECT Cno,COUNT(Sno)

FROM SC

GROUP BY Cno;

该语句对查询结果按Cno的值分组,所有具有相同Cno值的元组分为一组,然后对每一组作用聚集函数COUNT进行计算,以求得该组的学生人数。

如果分组后还要求按一定的条件对这些组进行筛选,最终只输出满足指定条件的组,则可以使用HAVING短语指定筛选条件。

【例3.47】查询选修了三门以上课程的学生学号。

SELECT Sno

FROM SC

GROUP BY Sno

HAVING COUNT(*)>3;

这里先用GROUP BY子句按Sno进行分组,再用聚集函数COUNT对每一组计数:HAVING短语给出了选择组的条件,只有满足条件(即元组个数>3,表示次学生选修的课超过3门)的组才会被选出来。

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

【例3.48】查询平均成绩大于等于90分的学生学号和平均成绩。

因为WHERE子句不能用聚集函数作为条件表达式,所以正确的查询语句应该是:

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>

当连接运算符为=时,称为等值连接。使用其他运算符称为非等值连接。

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

【例3.49】查询每个学生及其选修课程的情况。

学生情况存放在Student表中,学生选课情况存放在SC表中,所以本查询实际上涉及Student与SC两个表。这两个表之间的联系是通过公共属性Sno实现的。

SELECT Student.*, SC.*

FROM Student,SC

WHERE Student.Sno=SC.Sno; /*将Student与SC中同一学生的元组连接起来*/

本例中,SELECT子句与WHERE子句中的属性名前都加上了表名前缀,这是为了避免混淆。如果属性名在参加连接的各表中是唯一的,则可以省略表名前缀。

关系数据库管理系统执行该连接操作的一种可能过程是:首先在表Student中找到第一个元组,然后从头开始扫描SC表,逐一查找与Student第一个元组的Sno相等的SC元组,然后从头开始扫描SC表,逐一查找与Student第一个元组的Sno相等的SC元组,找到后就将Student中的第一个元组与该元组拼接起来,形成结果表中一个元组。SC全部查找完后,再找Student中第二个元组,然后再从头开始扫描SC,逐一查找满足连接条件的元组,找到后就将Student 中的第二个元组与该元组拼接起来,形成结果表中一个元组。重复上述操作,直到Student 中的全部元组都处理完毕为止。这就是嵌套循环连接算法的基本思想。

如果在SC表Sno上建立了索引的话,就不用每次全表扫描SC表了,而是根据Sno值通过索引找到相应的SC元组。用索引查询SC中满足条件的元组一般会比全表扫描快。

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

【例3.50】对例3.49用自然连接完成。

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade

FROM Student,SC

WHERE Student.Sno=SC.Sno;

本例中,由于Sname,Ssex,Sage,Sdept,Cno和Grade属性列在Student表与SC表中是唯一的,因此引用时可以去掉表名前缀;而Sno在两个表都出现了,因此引用时必须加上表名前缀。

一条SQL语句可以同时完成选择和连接查询,这时WHERE子句是由连接谓词和选择谓词组成的符合条件。

【例3.51】查询选修2号课程且成绩在90分以上的所有学生的学号和姓名。

SELECT Student,Sno,Sname

FROM Student,SC

WHERE Student.Sno=SC.Sno AND /*连接谓词*/

SC.Cno='2' AND SC.Grade>90; /*其他限定条件*/

该查询的一种优化(高效)的执行过程是,先从SC中挑选出Cno='2'并且Grade>90的元组形成一个中间关系,再和Student中满足连接条件的元组进行连接得到最终的结果关系。

2.自身连接

连接操作不仅可以在两个表之间进行,也可以是一个表与其自己进行连接,称为表的自身连接。

【例3.52】查询每一门课的间接先修课(即先修课的先修课)。

在Course表中只有每门课的直接先修课信息,而没有先修课的先修课。要得到这个信息,必须先对一门课找到其先修课,再按此先修课的课程号查找它的先修课程。这就要将Course表与其自身连接。

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

完成该查询的SQL语句为

SELECT FIRST.Cno,SECOND.Cpno

FROM Course FIRST,Course SECOND

WHERE FIRST.Cpno=SECOND.Cno;

3.外连接

在通常的连接操作中,只有满足连接条件的元组才能作为结果输出。

有时想以Student表作为主体列出每个学生的基本情况,及其选课情况。若某个学生没有选课,仍把Student的悬浮元组保存在结果关系中,而在SC表的属性上填空值NULL,这时就需要使用外连接。

可以参照例3.53改写例3.49。

【例3.53】

SELECT Student.Sno,Sname,Ssex,Sage,Sdept,Cno,Grade

FROM Student LEFT OUTER JOIN SC ON (Student.Sno=SC.Sno);

/*也可以使用USING来去掉结果中的重复值:FROM Student LEFT OUTER JOIN SC USING(Sno);*/

左外连接列出左边关系(如本例Student)中所有的元组,右外连接列出右边关系中所有的元组。

4.多表连接

连接操作除了可以是两表连接、一个表与其自身连接外,还可以是两个以上的表进行连接,后者通常称为多表连接。

【例3.54】查询每个学生的学号、姓名、选修的课程名及成绩。

本查询涉及三个表,完成该查询的SQL语句如下:

SELECT Student.Sno,Sname,Cname,Grade

FROM Student,SC,Course

WHERE Student.Sno=SC.Sno AND SC.Cno=Course.Cno;

关系数据库管理系统在执行多表连接时,通常是先进行两个表的连接操作,再将其连接结果与第三个表进行连接。本例的一种可能的执行方式是,现将Student表与SC表进行连接,得到每个学生的学号、姓名、所选课程号和相应的成绩,然后再将其与Course表进行连接,得到最终结果。

3.4.3 嵌套查询

在SQL语言中,一个SELECT-FROM-WHERE语句称为一个查询块。将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。例如:

SELECT Sname /*外层查询或父查询*/

FROM Student

WHERE Sno IN

(SELECT Sno /*内层查询或子查询*/

FROM SC

WHERE Cno='2')

本例中,下层查询块SELECT Sno FROM SC WHERE Cno='2'是嵌套在上层查询块SELECT Sname FROM Student WHERE Sno IN的WHERE条件中的。上层的查询块称为外层查询或父查询,下层查询块称为内层查询或子查询。

SQL语言允许多层嵌套查询,即一个子查询中还可以嵌套其他子查询。特别需要指出的是,子查询的SELECT语句中不能使用ORDER BY子句;ORDER BY子句只能对最终查询结果排序。

嵌套查询使用户可以用多个简单查询构成复杂的查询,从而增强SQL的查询能力。以层层嵌套的方式来构造程序正是SQL中“结构化”的含义所在。

1.带有IN谓词的子查询

在嵌套查询中,子查询的结果往往是一个集合,所以谓词IN是嵌套查询中最经常使用的谓词。

【例3.55】查询与“刘晨”在同一个系学习的学生。

先分步来完成此查询,然后再构造嵌套查询。

1)确定“刘晨”所在系名:

SELECT Sdept

FROM Student

WHERE Sname='刘晨';

结果为CS。

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

SELECT Sno,Sname,Sdept

FROM Student

WHERE Sdept='CS';

将第一步查询嵌入到第二步查询的条件中,构造嵌套查询如下:

SELECT Sno,Sname,Sdept /*例3.55的解法一*/

FROM Student

WHERE Sdept IN

(SELECT Sdept

FROM Student

WHERE Sname='刘晨');

本例中,子查询的查询条件不依赖于父查询,称为不相关子查询。一种求解方法是由里向外处理,即先执行子查询,子查询的结果用于建立其父查询的查找条件。得到如下的语句:

SELECT Sno,Sname,Sdept

FROM Student

WHERE Sdept IN ('CS');

然后执行该语句。

本例中的查询也可以用自身连接来完成:

SELECT S1.Sno,S1.Sname,S1.Sdept /*例3.55的解法二*/

FROM Student.S1,Student.S2

WHERE S1.Sdept=S2.Sdept AND S2.Sname='刘晨';

可见,实现同一个查询请求可以有多种方法,当然不同的方法其执行效率可能会有差别,甚至差别会很大。这就是数据库编程人员应该掌握的数据库性能调优技术。

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

本查询涉及学号、姓名和课程名三个属性。学号和姓名存放在Student表中,课程名存放在Course表中,但Student与Course两个表之间没有直接联系,必须通过SC表建立它们二者之间的关系。所以本查询实际上涉及三个关系。

SELECT Sno,Sname

FROM Student

WHERE Sno IN

(SELECT Sno

FROM SC

WHERE Cno IN

(SELECT Cno

FROM Course

WHERE Cname='信息系统'

)

);

1)首先,在Course关系中找出“信息系统”的课程号,结果为3号;

2)然后,在SC关系中找出选修了3号课程的学生学号;

3)最后,在Student关系中取出Sno和Sname。

本查询同样可以用连接查询实现。

SELECT Student,Sno,Sname

FROM Student,SC,Course

WHERE Student.Sno=SC.Sno AND

SC.Cno=Course.Cno AND

Course.Cname='信息系统';

有些嵌套查询可以用连接运算替代,有些是不能替代的。从例3.55和例3.56可以看到,查询涉及多个关系时,用嵌套查询逐步求解层次清楚,易于构造,具有结构化程序设计的优点。但是相比于连接运算,目前商用关系数据库管理系统对嵌套查询的优化做得还不够完善,所以在实际应用中,能够用连接运算表达的查询尽可能采用连接运算。

例3.55和例3.56中子查询的查询条件不依赖于父查询,这类子查询称为不相关子查询。不相关子查询是较简单的一类子查询。如果子查询的查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询语句。例3.57就是一个相关子查询的例子。

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

带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行连接。当用户能确切知道内层查询返回的是单个值的时候,可以用>、<、>=、<=、!=或<>等比较运算符。

例如在例3.55中,由于一个学生只可能在一个系学习,也就是说内查询的结果是一个值,因此可以用=代替IN:

SELECT Sno,Sname,Sdept

FROM Student

WHERE Sdept=

(SELECT Sdept

FROM Student

WHERE Sname='刘晨');

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

SELECT Sno,Cno

FROM SC x

WHERE Grade >=(SELECT AVG(Grade) /*某学生的平均成绩*/

FROM SC y

WHERE y.Sno=x.Sno);

x是表SC的别名,又称为元组变量,可以用来表示SC的一个元组。内层查询是求一个学生所有选修课程平均成绩的,至于是哪个学生的平均成绩要看参数x.Sno的值,而该值是与附查询相关的,因此这类查询称为相关子查询。

这个语句的一种可能的执行过程采用以下三个步骤:

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

SELECT AVG(Grade)

FROM SC y

WHERE y.Sno='201215121';

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

SELECT Sno,Cno

FROM SC x

WHERE Grade >= 88;

3)执行这个查询,得到

(201215121,1)

(201215121,3)

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

求解相关子查询不能像求解不相关子查询那样一次将子查询求解出来,然后求解父查询。内层查询由于与外层查询有关,因此必须反复求值。

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

子查询返回单值时可以用比较运算符,但返回多值时要用ANY(有的系统用SOME)或ALL谓词修饰符。而使用ANY或ALL谓词则必须同时使用比较运算符。其语义如下所示。

>ANY

大于子查询结果中的某个值

>ALL

大于子查询结果中的所有值

小于子查询结果中的某个值

小于子查询结果中的所有值

>=ANY

大于等于子查询结果中的某个值

>=ALL

大于等于子查询结果中的所有值

<=ANY

小于等于子查询结果中的某个值

<=ALL

小于等于子查询结果中的所有值

=ANY

等于子查询结果中的某个值

=ALL

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

!=(或<>)ANY

不等于子查询结果中的某个值

!=(或<>)ALL

不等于子查询结果中的任何一个值

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

SELECT Sname,Sage

FROM Student

WHERE Sage

FROM Student

WHERE Sdept='CS')

AND Sdept <>'CS'; /*注意:这是父查询块中的条件*/

关系数据库管理系统执行此查询时,首先处理子查询,找出CS系中所有学生的年龄,构成一个集合(20,19);然后处理父查询,找所有不是CS系且年龄小于20或19的学生。

本查询也可以用聚集函数来实现,首先用子查询找出CS系中最大年龄(20),然后在父查询中查所有非CS系且年龄小于20岁的学生。SQL语句如下:

SELECT Sname,Sage

FROM Student

WHERE Sage <

(SELECT Sage

FROM Student

WHERE Sdept='CS')

AND Sdept <>'CS';

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

SELECT Sname,Sage

FROM Student

WHERE Sage

(SELECT Sage

FROM Student

WHERE Sdept='CS')

AND Sdept <>'CS';

关系数据库管理系统执行此查询时,首先处理子查询,找出CS系中所有学生的年龄,构成一个集合(20,19)。然后处理父查询,找所有不是CS系且年龄既小于20,也小于19的学生。

本查询同样也可以用聚集函数实现。SQL语句如下:

SELECT Sname,Sage

FROM Student

WHERE Sage <

(SELECT MIN(Sage)

FROM Student

WHERE Sdept='CS')

AND Sdept <>'CS';

事实上,用聚集函数实现子查询通常比直接用ANY或ALL查询效率要高。ANY、ALL与聚集函数的对应关系如表3.7所示。

表3.7 ANY(或SOME)、ALL谓词与聚集函数、IN谓词的等价转换关系

=

<>或!=

<

<=

>

>=

ANY

IN

--

<=MAX

>MIN

>=MIN

ALL

--

NOT IN

<=MIN

>MAX

>=MAX

表3.7中,=ANY等价于IN谓词,ALL等价于NOT IN谓词,

4.带有EXISTS谓词的子查询

EXISTS代表存在量词∃。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。

可以利用EXISTS来判断x∈S、S⊆R、S=R、S∩R非空等是否成立。

【例3.60】查询所有选修了1号课程的学生姓名。

本查询涉及Student和SC表。可以在Student中依次取每个元组的Sno值,用此值去检查SC表。若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其Cno='1',则取此Student.Sname送入结果表。将此想法写成SQL语句是

SELECT Sname

FROM Student

WHERE EXISTS

(SELECT *

FROM SC

WHERE Sno=Student.Sno AND Cno='1');

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

由EXISTS引出的子查询,其目标列表达式通常都有*,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

本例中子查询的查询条件依赖于外层父查询的某个属性值(Student的Sno值),因此也是相关子查询。这个相关子查询的处理过程是:首先取外层查询中Student 表的第一个元组,根据它与内层查询相关的属性值(Sno值)处理内层查询,若WHERE子句返回值为真,则取外层查询中该元组的Sname放入结果表;然后再取Student 表的下一个元组:重复这一过程,直至外层Student 表全部检查完为止。

本例中的查询也可以用连接运算来实现,读者可以参照有关的例子自己给出相应的SQL语句。

与EXISTS谓词相对应的是NOT EXISTS谓词。使用存在量词NOT EXISTS后,若内层查询结果为空,则外层的WHERE子句返回真值,否则返回假值。

【例3.61】查询没有选修1号课程的学生姓名。

SELECT Sname

FROM Student

WHERE NOT EXISTS

(SELECT *

FROM SC

WHERE Sno=Student.Sno AND Cno='1');

一些带EXISTS或NOT EXISTS谓词的子查询不能被其他形式的子查询等价替换,但所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能用带EXISTS谓词的子查询等价替换。例如带有IN谓词的例3.55可以用如下带EXISTS谓词的子查询替换:

SELECT Sno,Sname,Sdept /*例3.55的解法四*/

FROM Student S1

WHERE EXISTS

(SELECT *

FROM Student S2

WHERE S2.Sdept=S1.Sdept AND

S2.Sname='刘晨')

由于带EXISTS量词的相关子查询只关心内层查询是否有返回值,并不需要查具体值,因此其效率并不一定低于不相关子查询,有时是高效的方法。

【例3.62】查询选修了全部课程的学生姓名。

SQL中没有全称量词(for all),但是可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:

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

由于没有全称量词,可将题目的意思转换成等价的用存在量词的形式:查询这样的学生,没有一门课程是他不选修的。其SQL语句如下:

SELECT Sname

FROM Student

WHERE NOT EXISTS

(SELECT *

FROM Course

WHERE NOT EXISTS

(SELECT *

FROM SC

WHERE Sno=Student.Sno

AND Cno=Course.Cno));

从而用EXIST/NOT EXIST来实现带全称量词的查询。

【例3.63】查询至少选修了学生201215122选修的全部课程的学生号码。

本查询可以用逻辑蕴涵来表达:查询学号为x的学生,对所有的课程y,只要201215122学生选修了课程y,则x也选修了y。形式化表示如下:

用p表示谓词“学生201215122选修了课程y”

用q表示谓词“学生x选修了课程y”

则上述查询为

(∀y)p→q

SQL语言中没有蕴涵逻辑运算,但是可以利用谓词演算将一个逻辑蕴涵的谓词等价转换为

p→q≡¬p∨q

该查询可以转换为如下等价形式:

(∀y)p→q≡¬(∃y(¬p→q))≡¬(∃y(¬(¬p∨q)))≡¬∃y(p∧¬q)

它所表达的语义为:不存在这样的课程y,学生201215122选修了y,而学生x没有选。用SQL语言表示如下:

SELECT DISTINCT Sno

FROM SC SCX

WHERE NOT EXISTS

(SELECT *

FROM SC SCY

WHERE SCY.Sno='201215122' AND

NOT EXISTS

(SELECT *

FROM SC SCZ

WHERE SCZ.Sno=SCX.Sno AND

SCZ.Cno = SCY.Cno));

3.4.4 集合查询

SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作。集合操作主要包括:并操作UNION、交操作INTERSECT和差操作EXCEPT。

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

【例3.64】查询计算机科学系的学生及年龄不大于19岁的学生。

SELECT *

FROM Student

WHERE Sdept='CS';

UNION

SELECT *

FROM Student

WHERE Sage <=19;

本查询实际上是求计算机科学系的所有学生与年龄不大于19岁的学生的并集。使用UNION将多个查询结果合并起来时,系统会自动去掉重复元组。如果要保留重复元组则用UNION ALL操作符。

【例3.65】查询选修了课程1或者选修了课程2的学生。

本例即查询选修课程1的学生集合与选修课程2的学生集合的并集。

SELECT Sno

FROM SC

WHERE Cno='1'

UNION

SELECT Sno

FROM SC

WHERE Cno='2';

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

SELECT *

FROM Student

WHERE Sdept='CS';

INTERSECT

SELECT *

FROM Student

WHERE Sage <=19;

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

SELECT *

FROM Student

WHERE Sdept='CS' AND

Sage<=19;

【例3.67】查询既选修了课程1又选修了课程2的学生。就是查询选修课程1的学生集合与选修课程2的学生集合的交集。

SELECT Sno

FROM SC

WHERE Cno='1'

INTERSECT

SELECT Sno

FROM SC

WHERE Cno='2';

本例也可以表示为

SELECT Sno

FROM SC

WHERE Cno='1' AND Sno IN

(SELECT Sno

FROM SC

WHERE Cno='2');

【例3.68】查询计算机科学系的学生与年龄不大于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子句中,这时子查询生成的临时派生表成为主查询的查询对象。例如,例3.57找出每个学生超过他自己选修课程平均成绩的课程号,也可以用如下的查询完成:

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

这里FROM子句中的子查询将生成一个派生表Avg_sc。该表由avg_sno和avg_grade两个属性组成,记录了每个学生的学号及平均成绩。主查询将SC表与Avg_sc按学号相等进行连接,选出修课成绩大于其平均成绩的课程号。

如果子查询中没有聚集函数,派生表可以不指定属性列,子查询SELECT子句后面的列名为其默认属性。例如例3.60查询所有选修了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语句是SQL的核心语句,从前面的例子可以看到其语句成分丰富多样,下面总结一下它们的一般格式。

SELECT语句的一般格式:

SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]···

FROM <>[,<表名或视图名>···] | ()[AS]<别名>

[WHERE <条件表达式>]

[GROUP BY<列名1>[HAVING<条件表达式>]]

[ORDER BY<列名2>[ASC|DESC]];

1.目标列表达式的可选格式

(1)*

(2)<表名>.*

(3)COUNT( [DISTINCT|ALL] *)

(4)[<表名>.]<属性列名表达式>[,[<表名>.]<属性列名表达式>]…

其中,<属性列名表达式>可以是由属性列、作用于属性列的聚集函数和常量的任意算术运算(加减乘除)组成的运算公式。

2.聚集函数的一般格式

《数据库系统概论》学习笔记_第11张图片

3.WHERE子句的条件表达式的可选格式

(1)

(2)

(3)

(4)<数据列名>[NOT] LIKE <匹配串>

(5)<数据列名> IS [NOT] NULL

(6)[NOT] EXISTS(SELECT 语句)

(7)

《数据库系统概论》学习笔记_第12张图片

3.5 数据更新

数据更新操作有三种:向表中添加若干行数据、修改表中的数据和删除表中的若干行数据。在SQL中有相应的三类语句。

3.5.1 插入数据

SQL的数据插入语句INSERT通常有两种形式,一种是插入一个元组,另一种是插入子查询结果。后者可以一次插入多个元组。

1.插入元组

插入元组的INSERT语句的格式为

INSERT

INTO <表名> [(<属性列1>[,<属性列2>]...)]

VALUES (<常量1>[,<常量2>]...)

其功能是将新元组插入指定表中。其中新元组的属性列1的值为常量1,属性列2的值为常量2,……。INTO子句中没有出现的属性列,新元组在这些列上将取空值。但必须注意的是,在表定义时说明了NOT NULL的属性列不能取空值,否则会出错。

如果INTO子句没有指明任何属性列名,则新插入的元组必须在每个属性列上均有值。

【例3.69】将一个新学生元组(学号:201215128,姓名:陈冬,性别:男,所在系:IS,年龄:18岁)插入到Student表中。

INSERT

INTO Student(Sno,Sname,Ssex,Sdept,Sage)

VALUES ('201215128','陈冬',男'',IS'',18);

在INTO子句中指出了表名Student,并指出了新增加的元组在哪些属性上要赋值,属性的顺序可以与CREATE TABLE中的顺序不一样。VALUES子句对新元组的各属性赋值,字符串常数要用单引号(英文符号)括起来。

【例3.70】将学生张成民的信息插入到Student表中。

INSERT

INTO Student

VALUES('201215126', '张成民', '男', 18, 'CS');

与例3.69不同的是,在INTO子句中只指出了表名,没有指出属性名。这表示新元组要在表的所有属性列上都指定值,属性列的次序与CREATE TABLE中的次序相同。VALUES子句对新元组的各属性列赋值,一定要注意值与属性列要一一对应,如果像例3.69那样,成为('201215126', '张成民', '男', 'CS', 18),则含义是将'CS'赋予了列Sage,而18赋予了列Sdept,这样则会因为数据类型不匹配而出错。

【例3.71】插入一条选课记录('201215128', '1')。

INSERT

INTO SC(Sno,Cno)

VALUES('201215128', '1');

关系数据库管理系统将在新插入记录的Grade列上自动地赋空值。

或者

INSERT

INTO SC

VALUES ('201215128', '1', NULL);

因为没有指出SC的属性值,在Grade列上要明确给出空值。

2.插入子查询结果

子查询不仅可以嵌套在SELECT语句中用以构造父查询的条件(如3.4.3小节所述),也可以嵌套在INSERT语句中用以生成要插入的批量数据。

插入子查询结果的INSERT语句格式为

INSERT

INTO <表名>(<属性列1>[,<属性列2>...])

子查询;

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

首先在数据库中建立一个新表,其中一列存放系名,另一列存放相应的学生平均年龄。

CREATE TABLE Dept_age

(Sdept CHAR(15)

Avg_age SMALLINT);

然后对Student表按系分组求平均年龄,再把系名和平均年龄存入新表中。

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.修改某一个元组的值

【例3.73】将学生201215121的年龄改为22岁。

UPDATE Student

SET Sage=22

WHERE Sno='201215121';

2.修改多个元组的值

【例3.74】将所有学生的年龄增加1岁。

UPDATE Student

SET Sage=Sage+1;

3.带子查询的修改语句

子查询也可以嵌套在UPDATE语句中,用以构造修改的条件。

【例3.75】将计算机科学系全体学生的成绩置零。

UPDATE SC

SET Grade=0

WHERE Sno IN

(SELECT Sno

FROM Student

WHERE Sdept='CS');

3.5.3 删除数据

删除语句的一般格式为

DELETE

FROM <表名>

[WHERE <条件>];

DELETE语句的功能是从指定表中删除满足WHERE子句条件的所有元组。如果省略WHERE子句则表示删除表中全部元组,但表的定义仍在字典中。也就是说,DELETE语句删除的是表中的数据,而不是关于表的定义。

1.删除某一个元组的值

【例3.76】删除学号为201215128的学生记录。

DELETE

FROM Student

WHERE Sno='201215128';

2.删除多个元组的值

【例3.77】删除所有的学生选课记录。

DELETE

FROM SC;

这条DELETE语句将使SC成为空表,它删除了SC的所有元组。

3.带子查询的删除语句

子查询同样也可以嵌套在DELETE语句中,用以构造执行删除操作的条件。

【例3.78】删除计算机科学系所有学生的选课记录。

DELETE

FROM SC

WHERE Sno IN

(SELETE Sno

FROM Student

WHERE Sdept='CS');

对某个基本表中数据的增、删、改操作有可能会破坏参照完整性,5.2节 参照完整性将详细讲解如何进行参照完整性检查和控制。

3.6 空值的处理

前面已经多处提到空值(NULL)的概念和空值的处理,这里再系统介绍一下这个问题。所谓空值就是“不知道"或“不存在”或“无意义”的值。SQL语言中允许某些元组的某些属性在一定情况下取空值。一般有以下几种情况:

●该属性应该有一个值,但目前不知道它的具体值。例如,某学生的年龄属性,因为学生登记表漏填了,不知道该学生年龄,因此取空值。

●该属性不应该有值。例如,缺考学生的成绩为空,因为他没有参加考试。

●由于某种原因不便于填写。例如,一个人的电话号码不想让大家知道,则取空值。

因此,空值是一个很特殊的值,含有不确定性,对关系运算带来特殊的问题,需要做特殊的处理。

1.空值的产生

【例3.79】向SC表中插入一个元组,学生号是“201215126”,课程号是“1”,成绩为空。

INSERT INTO SC(Sno,Cno,Grade)

VALUES('201215126', '1', NULL); /*在插入时该学生还没有考试成绩,取空值*/

INSERT INTO SC(Sno,Cno)

VALUES('201215126','1'); /*在插入语句中没有赋值的属性,其值为空值*/

【例3.80】将Student表中学生号为“201215200”的学生所属的系改为空值。

UPDATE Student

SET Sdept=NULL

WHERE Sno='201215200';

另外,外连接也会产生空值,参见3.4.2小节。空值的关系运算也会产生空值。

2.空值的判断

判断一个属性的值是否为空值,用IS NULL或IS NOT NULL来表示。

【例3.81】从Student表中找出漏填了数据的学生信息。

SELECT *

FROM Student

WHERE Sname IS NULL OR Ssex IS NULL OR Sage IS NULL OR Sdept IS NULL;

3.空值的约束条件

属性定义(或者域定义)中有NOT NULL约束条件的不能取空值,加了UNIQUE限制的属性不能取空值,加了UNIQUE限制的属性不能取空值,码属性不能取空值。

4.空值的算术运算、比较运算和逻辑运算

空值与另一个值(包括另一个空值)的算术运算的结果为空值,空值与另一个值(包括另一个空值)的比较运算的结果为UNKNOWN。有了UNKNOWN后,传统的逻辑运算中二值(TRUE,FALSE)逻辑就扩展成了三值逻辑。AND、OR、NOT的真值表如表3.8所示,其中T表示TRUE,F表示FALSE,U表示UNKNOWN。

在查询语句中,只有使WHERE和HAVING子句中的选择条件为TRUE的元组才被选出作为输出结果。

《数据库系统概论》学习笔记_第13张图片

【例3.82】找出选修1号课程的不及格的学生。

SELECT Sno

FROM SC

WHERE Grade < 60 AND Cno='1';

选出的学生是那些参加了考试(Grade属性为非空值)而不及格的学生,不包括缺考的学生。因为前者使条件Grade <60的值为TRUE,后者使条件的值为UNKNOWN。

【例3.83】选出选修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 视图

视图是从一个或几个基本表(或视图)导出的表。它与基本表不同,是一个虚表。数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。所以一旦基本表中的数据发生变化,从视图中查询出的数据也就随之改变了。从这个意义上讲,视图就像一个窗口,透过它可以看到数据库中自己感兴趣的数据及其变化。

视图一经定义,就可以和基本表样被查询、 被删除。也可以在一个视图之上再定义新的视图,但对视图的更新(增、删、改)操作则有一定的限制。

本节专门讨论视图的定义、操作及作用。

3.7.1 定义视图

1.建立视图

SQL语言用CREATE VIEW命令建立视图,其一般格式为

CREATE VIEW<视图名> [(<列名> [,<列名>]… )]

AS <子查询>

[WITH CHECK OPTION] ;

其中,子查询可以是任意的SELECT语句,是否可以含有ORDER BY子句和DISTINCT短语,则取决于具体系统的实现。

WITH CHECK OPTION表示对视图进行UPDATE、INSERT 和DELETE操作时要保证更新、插入或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。

组成视图的属性列名或者全部省略或者全部指定,没有第三种选择。如果省略了视图的各个属性列名,则隐含该视图由子查询中SELECT子句目标列中的诸字段组成。但在下列三种情况下必须明确指定组成视图的所有列名:

(1)某个目标列不是单纯的属性名,而是聚集函数或列表达式;

(2)多表连接时选出了几个同名列作为视图的字段;

(3)需要在视图中为某个列启用新的更合适的名字。

【例3.84】 建立信息系学生的视图。

CREATE VIEW IS_ Student

AS

SELECT Sno,Sname,Sage

FROM Student

WHERE Sdept='IS';

本例中省略了视图IS_ Student 的列名,隐含了由子查询中SELECT子句中的三个列名组成。

关系数据库管理系统执行CREATE VIEW语句的结果只是把视图的定义存入数据字典,并不执行其中的SELECT语句。只是在对视图查询时,才按视图的定义从基本表中将数据查出。

[例3.85] 建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生。

CREATE VIEW IS_ Student

AS

SELECT Sno,Sname,Sage

FROM Student

WHERE Sdept='IS'

WITH CHECK OPTION;

由于在定义IS_ Student 视图时加上了WITH CHECK OPTION子句,以后对该视图进行插入、修改和删除操作时,关系数据库管理系统会自动加上Sdept='IS'的条件。

若一个视图是从单个基本表导出的,并且只是去掉了基本表的某些行和某些列,但保留了主码,则称这类视图为行列子集视图。IS_ Student 视图就是一个行列子集视图。

视图不仅可以建立在单个基本表上,也可以建立在多个基本表上。

[例3.86] 建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)。

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';

由于视图IS_S1的属性列中包含了Student表与SC表的同名列Sno,所以必须在视图名后面明确说明视图的各个属性列名。

视图不仅可以建立在一或多个基本表上,也可以建立在一个或多个已定义好的视图上,或建立在基本表与视图上。

[例3.87] 建立信息系选修了1号课程且成绩在90分以上的学生的视图。

CREATE VIEW IS_S2

AS

SELECT Sno,Sname,Grade

FROM IS_ S1

WHERE Grade>=90;

这里的视图IS_S2就是建立在视图IS_S1之上的。

定义基本表时,为了减少数据库中的冗余数据,表中只存放基本数据,由基本数据经过各种计算派生出的数据一般是不存储的。由于视图中的数据并不实际存储,所以定义视图时可以根据应用的需要设置一些派生属性列。这些派生属性由于在基本表中并不实际存在,也称它们为虚拟列。带虚拟列的视图也称为带表达式的视图。

[例3.88] 定义一个反映学生出生年份的视图。

CREATE VIEW BT_S(Sno,Sname,Sbirth)

AS

SELECT Sno,Sname,2014-Sage

FROM Student;

这里视图BT_S是一个带表达式的视图。视图中的出生年份值是通过计算得到的。

还可以用带有聚集函数和GROUP BY子句的查询来定义视图,这种视图称为分组视图

[例3.89] 将学生的学 号及平均成绩定义为一个视图。

CREATE VIEW S_ G(Sno,Gavg)

AS

SELECT Sno,AVG(Grade)

FROM SC

GROUP BY Sno;

由于AS子句中SELECT语句的目标列平均成绩是通过作用聚集函数得到的,所以CREATE VIEW中必须明确定义组成S_G视图的各个属性列名。S_G是一个分组视图。

[例3.90] 将Student表中所有女生记录定义为一个视图。

CREATE VIEW F Student(F_ sno,name,sex,age,dept)

AS

SELECT *

FROM Student

WHERE Ssex='女;

这里视图F_ Student 是由子查询“SELECT *”建立的。F_Student 视图的属性列与Student表的属性列一一对应。 如果以后修改了基本表Student的结构,则Student 表与F_Student视图的映像关系就会被破坏,该视图就不能正常工作了。为避免出现这类问题,最好在修改基本表之后删除由该基本表导出的视图,然后重建这个视图。

2.删除视图

该语句的格式为

DROP VIEW <视图名> [CASCADE] ;

视图删除后视图的定义将从数据字典中删除。如果该视图上还导出了其他视图,则使用CASCADE级联删除语句把该视图和由它导出的所有视图。起删除。

基本表删除后,由该基本表导出的所有视图均无法使用了,但是视图的定义没有从字典中清除。删除这些视图定义需要显式地使用DROP VIEW语句。

[例3.91] 删除视图BT_S和视图IS_ S1:

DROP VIEW BT_S; /*成功执行*/

DROP VIEW IS_ S1; /*拒绝执行*/

执行此语句时由于IS_S1视图上还导出了IS_S2视图,所以该语句被拒绝执行。如果确定要删除,则使用级联删除语句:

DROP VIEW IS_S1 CASCADE; /*删除了视图IS_ S1和由它导出的所有视图*/

3.7.2 查询视图

视图定义后,用户就可以像对基本表一样对视图进行查询了。

[例3.92] 在信息系学生的视图中找出年龄小于20岁的学生。

SELECT Sno,Sage

FROM IS_Student

WHERE Sage<20;

关系数据库管理系统执行对视图的查询时,首先进行有效性检查,检查查询中涉及的表、视图等是否存在。如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询。这一转换过程称为视图消解(view resolution)。

本例转换后的查询语句为

SELECT Sno,Sage

FROM Student

WHERE Sdept='IS' AND Sage<20;

[例3.93] 查询选修了 1号课程的信息系学生。

SELECT IS_Student.Sno,Sname

FROM IS_Student,SC

WHERE IS_Student.Sno=SC.Sno AND SC.Cno='1';

本查询涉及视图IS_Student (虚表)和基本表SC,通过这两个表的连接来完成用户请求。

在一般情况下,视图查询的转换是直截了当的。但有些情况下,这种转换不能直接进行,查询时就会出现问题,如例3.94。

【例3.94】 在S_G视图(例3.89中定义的视图)中查询平均成绩在90分以上的学生学号和平均成绩,语句为

SELECT *

FROM S_G

WHERE Gavg >=90;

例3.89中定义S_G视图的子查询为

SELECT Sno,AVG(Grade)

FROM SC

GROUP BY Sno;

将本例中的查询语句与定义S_G视图的子查询结合,形成下列查询语句:

SELECT Sno,AVG(Grade)

FROM SC

WHERE AVG(Grade)>=90

GROUP BY Sno;

因为WHERE子句中是不能用聚集函数作为条件表达式的,因此执行此修正后的查询将会出现语法错误。正确转换的查询语句应该是

SELECT Sno,AVG(Grade)

FROM SC

GROUP BY Sno

HAVING AVG(Grade)>=90;

目前多数关系数据库系统对行列子集视图的查询均能进行正确转换。但对非行列子集视图的查询(如例3.94)就不一定能做转换了,因此这类查询应该直接对基本表进行。

例3.94也可以用如下SQL语句完成:

SELECT *

FROM (SELECT Sno,AVG(Grade) /*子查询生成一个派生表S_G*/

FROM SC

GROUP BY Sno) AS S_G(Sno,Gavg)

WHERE Gavg>=90;

但定义视图并查询视图与基于派生表的查询是有区别的。视图一旦定义,其定义将永久保存在数据字典中,之后的所有查询都可以直接引用该视图。而派生表只是在语句执行时临时定义,语句执行后该定义即被删除。

3.7.3 更新视图

更新视图是指通过视图来插入(INSERT)、删除(DELETE)和修改(UPDATE)数据。

由于视图是不实际存储数据的虚表,因此对视图的更新最终要转换为对基本表的更新。像查询视图那样,对视图的更新操作也是通过视图消解,转换为对基本表的更新操作。

为防止用户通过视图对数据进行增加、删除、修改时,有意无意地对不属于视图范围内的基本表数据进行操作,可在定义视图时加上WITH CHECK OPTION子句。这样在视图上增、删、改数据时,关系数据库管理系统会检查视图定义中的条件,若不满足条件则拒绝执行该操作。

[例3.95] 将信息系学生视图IS_ Student 中学号为“201215122”的学生姓名改为“刘辰”。

UPDATE IS Student

SET Sname='刘辰'

WHERE Sno ='201215122';

转换后的更新语句为

UPDATE Student

SET Sname='刘辰'

WHERE Sno='201215122' AND Sdept='IS';

[例3.96] 向信息系学生视图 IS_ Student 中插入一个新的学生记录,其中学号为“201215129”,姓名为“赵新”,年龄为20岁。

INSERT

INTO IS_ Student

VALUES('201215129', '赵新', 20);

转换为对基本表的更新:

INSERT

INTO Student(Sno,Sname,Sage,Sdept)

VALUES('201215129','赵新',20,'IS' );

这里系统自动将系名'IS'放入VALUES子句中。

[例3.97] 删除信息系学生视图IS_Student 中学号为“201215129” 的记录。

DELETE

FROM IS_ Student

WHERE Sno='201215129';

转换为对基本表的更新:

DELETE

FROM Student

WHERE Sno='201215129' AND Sdept='IS';

在关系数据库中,并不是所有的视图都是可更新的,因为有些视图的更新不能唯一地有意义地转换成相应基本表的更新。

例如,例3.89定义的视图S_G是由学号和平均成绩两个属性列组成的,其中平均成绩一项是由Student表中对元组分组后计算平均值得来的:

CREATE VIEW S_G(Sno,Gavg)

AS

SELECT Sno,AVG(Grade)

FROM SC

GROUP BY Sno;

如果想把视图S_G中学号为“201215121”的学生的平均成绩改成90分,SQL语句如下:

UPDATE S_G

SET Gavg=90

WHERE Sno='201215121';

但这个对视图的更新是无法转换成对基本表SC的更新的,因为系统无法修改各科成绩,以使平均成绩成为90.所以S_G视图是不可更新的。

一般地,行列子集视图是可更新的。除行列子集视图外,有些视图理论上是可更新的,但它们的确切特征还是尚待研究的课题。还有些视图从理论上就是不可更新的。

目前,各个关系数据库管理系统一般都只允许对行列子集视图进行更新,而且各个系统对视图的更新还有更进一步的规定。由于各系统实现方法上的差异,这些规定也不尽相同。

例如,DB2规定:

(1)若视图是由两个以上基本表导出的,则此视图不允许更新。

(2)若视图的字段来自字段表达式或常数,则不允许对此视图执行INSERT和UPDATE操作,但允许执行DELETE操作。

(3)若视图的字段来自聚集函数,则此视图不允许更新。

(4)若视图定义中含有GROUP BY子句,则此视图不允许更新。

(5)若视图定义中含有DISTINCT短语,则此视图不允许更新。

(6)若视图定义中有嵌套查询,并且内层查询的FROM子句中涉及的表也是导出该视图的基本表,则此视图不允许更新。例如,将SC表中成绩在平均成绩之上的元组定义成一个视图GOOD SC:

CREATE VIEW GOOD SC

AS

SELECT Sno,Cno,Grade

FROM SC

WHERE Grade>

(SELECT AVG(Grade)

FROM SC);

导出视图GOOD_SC的基本表是SC,内层查询中涉及的表也是SC, 所以视图GOOD_SC是不允许更新的。

(7) 一个不允许更新的视图上定义的视图也不允许更新。

应该指出的是,不可更新的视图与不允许更新的视图是两个不同的概念。前者指理论上已证明其是不可更新的视图。后者指实际系统中不支持其更新,但它本身有可能是可更新的视图。

3.7.4 视图的作用

视图最终是定义在基本表之上的,对视图的一切操作最终也要转换为对基本表的操作。而且对于非行列子集视图进行查询或更新时还有可能出现问题。既然如此,为什么还要定义视图呢?这是因为合理使用视图能够带来许多好处。

1.视图能够简化用户的操作

视图机制使用户可以将注意力集中在所关心的数据上。如果这些数据不是直接来自基本

表,则可以通过定义视图使数据库看起来结构简单、清晰,并且可以简化用户的数据查询操作。

例如,那些定义了若干张表连接的视图就将表与表之间的连接操作对用户隐蔽起来了。换句话

说,用户所做的只是对一个虚表的简单查询,而这个虚表是怎样得来的,用户无须了解。

2.视图使用户能以多种角度看待同一数据

视图机制能使不同的用户以不同的方式看待同一数据,当许多不同种类的用户共享同一个数据库时,这种灵活性是非常重要的。

3.视图对重构数据库提供了一定程度的逻辑独立性

第1章中已经介绍过数据的物理独立性与逻辑独立性的概念。数据的物理独立性是指用户的应用程序不依赖于数据库的物理结构。数据的逻辑独立性是指当数据库重构造时,如增加新的关系或对原有关系增加新的字段等,用户的应用程序不会受影响。层次数据库和网状数据库一般能较好地支持数据的物理独立性,而对于逻辑独立性则不能完全地支持。在关系数据库中,数据库的重构往往是不可避免的。重构数据库最常见的是将一个基本表“垂直”地分成多个基本表。例如:将学生关系

Student(Sno,Sname,Ssex,Sage,Sdept)

分为SX(Sno, Sname, Sage)和 SY(Sno, Ssex, Sdept)两个关系。 这时原表Student为SX表和SY表自然连接的结果。如果建立一个视图Student:

CREATE VIEW Student(Sno,Sname,Ssex,Sage,Sdept)

AS

SELECT SX.Sno,SX.Sname,SY.Ssex,SX.Sage,SY.Sdept

FROM SX,SY

WHERE SX.Sno=SY.Sno;

这样尽管数据库的逻辑结构改变了(变为SX和SY两个表),但应用程序不必修改,因为新建立的视图定义为用户原来的关系,使用户的外模式保持不变,用户的应用程序通过视图仍然能够查找数据。

当然,视图只能在一定程度上提供数据的逻辑独立性,比如由于对视图的更新是有条件的,因此应用程序中修改数据的语句可能仍会因基本表结构的改变而需要做相应修改。

4.视图能够对机密数据提供安全保护

有了视图机制,就可以在设计数据库应用系统时对不同的用户定义不同的视图,使机密数据不出现在不应看到这些数据的用户视图上。这样视图机制就自动提供了对机密数据的安全保护功能。例如,Student 表涉及全校15个院系的学生数据,可以在其上定义15个视图,每个视图只包含一个院系的学生数据,并只允许每个院系的主任查询和修改本院系的学生视图。

5.适当利用视图可以更清晰地表达查询

例如,经常需要执行这样的查询“对每个同学找出他获得最高成绩的课程号”。可以先定义一个视图,求出每个同学获得的最高成绩:

CREATE VIEW VMGRADE

AS

SELECT Sno,MAX(Grade) Mgrade

FROM SC

GROUP BY Sno;

然后用如下的查询语句完成查询:

SELECT SC.Sno,Cno

FROM SC, VMGRADE

WHERE SC.Sno=VMGRADE.Sno AND SC.Grade=VMGRADE.Mgrade;

第4章 数据库安全性

在第一章中已经讲到,数据库的特点之一是由数据库管理系统提供统一的数据保护功能来保证数据的安全可靠和正确有效。数据库的数据保护主要包括数据的安全性和完整性。本章主要介绍数据库的安全性,第5章将讨论数据库的完整性。

4.1 数据库安全性概述

数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄露、更改或破坏。

安全性问题不是数据库系统所独有的,所有计算机系统都存在不安全因素,只是在数据库系统中由于大量数据集中存放,而且为众多最终用户直接共享,从而使安全性问题更为突出。系统安全保护措施是否有效是数据库系统的主要技术指标之一。

4.1.1数据库的不安全因素

对数据库安全性产生威胁的因素主要有以下几方面。

1.非授权用户对数据库的恶意存取和破坏

一些黑客(hacker) 和犯罪分子在用户存取数据库时猎取用户名和用户口令,然后假冒合法用户偷取、修改甚至破坏用户数据。因此,必须阻止有损数据库安全的非法操作,以保证数据免受未经授权的访问和破坏,数据库管理系统提供的安全措施主要包括用户身份鉴别、存取控制和视图等技术。

2.数据库中重要或敏感的数据被泄露

黑客和敌对分子千方百计盗窃数据库中的重要数据,一些机密信息被暴露。为防止数据泄露,数据库管理系统提供的主要技术有强制存取控制、数据加密存储和加密传输等。

此外,在安全性要求较高的部门提供审计功能,通过分析审计日志,可以对潜在的威胁提前采取措施加以防范,对非授权用户的入侵行为及信息破坏情况能够进行跟踪,防止对数据库安全责任的否认。

3.安全环境的脆弱性

数据库的安全性与计算机系统的安全性,包括计算机硬件、操作系统、网络系统等的安全性是紧密联系的。操作系统安全的脆弱,网络协议安全保障的不足等都会造成数据库安全性的破坏。因此,必须加强计算机系统的安全性保证。随着Internet 技术的发展,计算机安全性问题越来越突出,对各种计算机及其相关产品、信息系统的安全性要求越来越高。为此,在计算机安全技术方面逐步发展建立了一套可信(trusted) 计算机系统的概念和标准。只有建立了完善的可信标准即安全标准,才能规范和指导安全计算机系统部件的生产,较为准确地测定产品的安全性能指标,满足民用和军用的不同需要。

4.1.2 安全标准简介

计算机以及信息安全技术方面有一系列的安全标准,最有影响的当推TCSEC和CC这两个标准。

TCSEC是指1985年美国国防部(Department of Defense, DoD)正式颁布的《DoD可信计算机系统评估准则》(Trusted Computer System Evaluation Criteria, TCSEC或DoD85)。

在TCSEC推出后的10年里,不同的国家都开始启动开发建立在TCSEC概念上的评估准则,如欧洲的信息技术安全评估准则( Information Technology Security EvaluationCriteria, ITSEC)、 加拿大的可信计算机产品评估准则(Canadian Trusted Computer ProductEvaluation Criteria, CTCPEC)、美国的信息技术安全联邦标准( Federal Criteria, FC)草案等。这些准则比TCSEC更加灵活,适应了IT技术的发展。

为满足全球IT市场上互认标准化安全评估结果的需要,CTCPEC、FC、TCSEC和ITSEC的发起组织于1993年起开始联合行动,解决原标准中概念和技术上的差异,将各自独立的准则集合成组单一的、能被广泛使用的IT安全准则,这一行动被称为通用准则(Common Criteria, CC)项目。项目发起组织的代表建立了专门的委员会来开发通用准则,历经多次讨论和修订,CCV2.1版于1999年被ISO采用为国际标准,2001年被我国采用为国家标准。

目前CC已经基本取代了TCSEC,成为评估信息产品安全性的主要标准。本节简要介绍TCSEC和CC V2.1的基本内容。

TCSEC又称桔皮书。1991年4月,美国国家计算机安全中心( National Computer SecurityCenter, NCSC)颁布了《可信计算机系统评估准则关于可信数据库系统的解释》(TCSECTrusted Database Interpretation, TCSEC/TDI, 即紫皮书),将TCSEC扩展到数据库管理系统。TCSECTDI中定义了数据库管理系统的设计与实现中需满足和用以进行安全性级别评估的标准,从4个方面来描述安全性级别划分的指标,即安全策略、责任、保证和文档。每个方面又细分为若干项。

根据计算机系统对各项指标的支持情况,TCSEC/TDI将系统划分为4组7个等级,依次是D、C(C1,C2)、B(B1,B2,B3)、A(A1),按系统可靠或可信程度逐渐增高,如表4.1所示。

表4.1 TCSEC/TDI安全级别划分

安全级别

定义

A1

验证设计

B3

安全域

B2

结构化保护

B1

标记安全保护

C2

受控的存取保护

C1

自主安全保护

D

最小保护

D级:该级是最低级别。保留D级的目的是为了将一切不符合更高标准的系统统统归于D组。如DOS就是操作系统中安全标准为D级的典型例子,它具有操作系统的基本功能,如文件系统、进程调度等,但在安全性方面几乎没有什么专门的机制来保障。

C1级:该级只提供了非常初级的自主安全保护,能够实现对用户和数据的分离,进行自主存取控制(DAC), 保护或限制用户权限的传播。现有的商业系统往往稍作改进即可满足要求。

C2级:该级实际上是安全产品的最低档,提供受控的存取保护,即将C1级的DAC进一步细化,以个人身份注册负责,并实施审计和资源隔离。达到C2级的产品在其名称中往往不突出“安全”(security) 这特色,如操作系统中的Windows 2000、数据库产品中的Oracle 7等。

B1级:标记安全保护。对系统的数据加以标记,并对标记的主体和客体实施强制存取控制(MAC)以及审计等安全机制。B1级别的产品才被认为是真正意义上的安全产品,满足此级别的产品前一般多冠以“安全”(security) 或“可信的”(trusted) 字样,作为区别于普通产品的安全产品出售。

B2级:结构化保护。建立形式化的安全策略模型,并对系统内的所有主体和客体实施DAC和MAC。

B3级:安全域。该级的TCB (Trusted Computing Base)必须满足访问监控器的要求,审计跟踪能力更强,并提供系统恢复过程。

A1级:验证设计,即提供B3级保护的同时给出系统的形式化设计说明和验证,以确信各安全保护真正实现。

CC是在上述各评估准则及具体实践的基础上通过相互总结和互补发展而来的。和早期的评估准则相比,CC具有结构开放、表达方式通用等特点。CC提出了目前国际上公认的表述信息技术安全性的结构,即把对信息产品的安全要求分为安全功能要求和安全保证要求。安全功能要求用以规范产品和系统的安全行为,安全保证要求解决如何正确有效地实施这些功能。安全功能要求和安全保证要求都以“类-子类-组件”的结构表述,组件是安全要求的最小构件块。

CC的文本由三部分组成,三个部分相互依存,缺一不可。

第一部分是简介和一般模型,介绍CC中的有关术语、基本概念和一般模型以及与评估有关的一些框架。

第二部分是安全功能要求,列出了一系列类、子类和组件。由11大类、66个子类和135个组件构成。

第三部分是安全保证要求,列出了一系列保证类、子类和组件,包括7大类、26个子类和74个组件。根据系统对安全保证要求的支持情况提出了评估保证级(EvaluationAssurance Level, EAL), 从EAL至EAL7共分为7级,按保证程度逐渐增高。如表4.2所示。

《数据库系统概论》学习笔记_第14张图片

CC的附录部分主要介绍保护轮廓(Protection Profile, PP)和安全目标(Security Target, ST)的基本内容。

这三部分的有机结合具体体现在保护轮廓和安全目标中,CC提出的安全功能要求和安全保证要求都可以在具体的保护轮廓和安全目标中进一步细化和扩展,这种开放式的结构更适应信息安全技术的发展。CC的具体应用也是通过保护轮廓和安全目标这两种结构来实现的。

粗略而言,TCSEC的C1和C2级分别相当于EAL2和EAL3; B1、B2和B3分别相当于EAL4、EAL5和EAL6; A1 对应于EAL7。

4.2 数据库安全性控制

下面讨论与数据库有关的安全性,主要包括用户身份鉴别、多层存取控制、审计、视图和数据加密等安全技术。

数据库安全保护的一个存取控制流程:首先,数据库管理系统对提出SQL访问请求的数据库用户进行身份鉴别,防止不可信用户使用系统;然后,在SQL处理层进行自主存取控制和强制存取控制,进一步还可以进行推理控制。为监控恶意访问,可根据具体安全需求配置审计规则,对用户访问行为和系统关键操作进行审计。通过设置简单入侵检测规则,对异常用户行为进行检测和处理。在数据存储层,数据库管理系统不仅存放用户数据,还存储与安全有关的标记和信息(称为安全数据),提供存储加密功能等。

4.2.1用户身份鉴别

用户身份鉴别是数据库管理系统提供的最外层安全保护措施。每个用户在系统中都有一个用户标识。每个用户标识由用户名(user name)和用户标识号(UID) 两部分组成。UID在系统的整个生命周期内是唯的。系统内部记录着所有合法用户的标识,系统鉴别是指由系统提供一定的方式让用户标识自己的名字或身份。每次用户要求进入系统时,由系统进行核对,通过鉴定后才提供使用数据库管理系统的权限。

用户身份鉴别的方法有很多种,而且在一个系统中往往是多种方法结合,以获得更强的安全性。常用的用户身份鉴别方法有以下几种。

1.静态口令鉴别

这种方式是当前常用的鉴别方法。静态口令一般由用户自己设定,鉴别时只要按要求输入正确的口令,系统将允许用户使用数据库管理系统。这些口令是静态不变的,在实际应用中,用户常常用自己的生日、电话、简单易记的数字等内容作为口令,很容易被破解。而一旦被破解,非法用户就可以冒充该用户使用数据库。因此,这种方式虽然简单,但容易被攻击,安全性较低。

口令的安全可靠对数据库安全来说至关重要。因此,数据库管理系统从口令的复杂度,口令的管理、存储及传输等多方面来保障口令的安全可靠。例如,要求口令长度至少是8个(或者更多)字符;口令要求是字母、数字和特殊字符混合,其中,特殊符号是除空白符、英文字母、单引号和数字外的所有可见字符。在此基础上,管理员还能根据应用需求灵活地设置口令强度,例如,设定口令中数字、字母或特殊符号的个数:设置口令是否可以是简单的常见单词,是否允许口令与用户名相同;设置重复使用口令的最小时间间隔等。此外,在存储和传输过程中口令信息不可见,均以密文方式存在。用户身份鉴别可以重复多次。

2.动态口令鉴别

它是目前较为安全的鉴别方式。这种方式的口令是动态变化的,每次鉴别时均需使用动态产生的新口令登录数据库管理系统,即采用一次一密的方法。常用的方式如短信密码和动态令牌方式,每次鉴别时要求用户使用通过短信或令牌等途径获取的新口令登录数据库管理系统。与静态口令鉴别相比,这种认证方式增加了口令被窃取或破解的难度,安全性相对高一些。

3.生物特征鉴别

它是一种通过生物特征进行认证的技术,其中,生物特征是指生物体唯一具有的,可测量、识别和验证的稳定生物特征,如指纹、虹膜和掌纹等。这种方式通过采用图像处理和模式识别等技术实现了基于生物特征的认证,与传统的口令鉴别相比,无疑产生了质的飞跃,安全性较高。

4.智能卡鉴别

智能卡是一种不可复制的硬件,内置集成电路的芯片,具有硬件加密功能。智能卡由用户随身携带,登录数据库管理系统时用户将智能卡插入专用的读卡器进行身份验证。由于每次从智能卡中读取的数据是静态的,通过内存扫描或网络监听等技术还是可能截取到用户的身份验证信息,存在安全隐患。因此,实际应用中一般采用个人身份识别码(PIN) 和智能卡相结合的方式。这样,即使PIN或智能卡中有一种被窃取,用户身份仍不会被冒充。

4.2.2 存取控制

数据库安全最重要的一点就是确保只授权给有资格的用户访问数据库的权限,同时令所有未被授权的人员无法接近数据,这主要通过数据库系统的存取控制机制实现。存取控制机制主要包括定义用户权限和合法权限检查两部分。

(1)定义用户权限,并将用户权限登记到数据字典中

用户对某一数据对象的操作权力称为权限。某个用户应该具有何种权限是个管理问题和政策问题,而不是技术问题。数据库管理系统的功能是保证这些决定的执行。为此,数据库管理系统必须提供适当的语言来定义用户权限,这些定义经过编译后存储在数据字典中,被称做安全规则或授权规则。

(2)合法权限检查

每当用户发出存取数据库的操作请求后(请求、 般应包括操作类型、操作对象和操作用户等信息),数据库管理系统查找数据字典,根据安全规则进行合法权限检查,若用户的操作请求超出了定义的权限,系统将拒绝执行此操作。

定义用户权限和合法权限检查机制一起组成了数据库管理系统的存取控制子系统。

C2级的数据库管理系统支持自主存取控制(Discretionary Access Control, DAC), B1级的数据库管理系统支持强制存取控制(Mandatory Access Control, MAC)。

这两类方法的简单定义是:

(1)在自主存取控制方法中,用户对于不同的数据库对象有不同的存取权限,不同的用户对同一对象也有不同的权限,而且用户还可将其拥有的存取权限转授给其他用户。因此自主存取控制非常灵活。

(2)在强制存取控制方法中,每一个数据库对象被标以一定的密级,每一个用户也被授予某一个级别的许可证。对于任意一个对象,只有具有合法许可证的用户才可以存取。强制存取控制因此相对比较严格。

下面介绍这两种存取控制方法。

4.2.3 自主存取控制方法

大型数据库管理系统都支持自主存取控制,SQL 标准也对自主存取控制提供支持,这主要通过SQL的GRANT语句和REVOKE语句来实现。

用户权限是由两个要素组成的:数据库对象和操作类型。定义一个用户的存取权限就是要定义这个用户可以在哪些数据库对象上进行哪些类型的操作。在数据库系统中,定义存取权限称为授权(authorization)。

在非关系系统中,用户只能对数据进行操作,存取控制的数据库对象也仅限于数据本身。

在关系数据库系统中,存取控制的对象不仅有数据本身(基本表中的数据、属性列上的数据),还有数据库模式(包括数据库、基本表、视图和索引的创建等),表4.3列出了主要的存取权限。

《数据库系统概论》学习笔记_第15张图片

表4.3中,列权限包括SELECT、REFERENCES、INSERT、 UPDATE,其含义与表权限类似。需要说明的是,对列的UPDATE权限指对于表中存在的某一列的值可以进行修改。当然,有了这个权限之后,在修改的过程中还要遵守表在创建时定义的主码及其他约束。列上的INSERT权限指用户可以插入一个元组。对于插入的元组,授权用户可以插入指定的值,其他列或者为空,或者为默认值。在给用户授予列INSERT权限时,一定要包含主码的INSERT权限,否则用户的插入动作会因为主码为空而被拒绝。

4.2.4 授权:授予与收回

SQL中使用GRANT和REVOKE语句向用户授子或收回对数据的操作权限。GRANT语句向用户授予权限,REVOKE语句收回已经授予用户的权限。

1. GRANT

GRANT语句的一般格式为

GRANT <权限> [,<权限>]…

ON <对象类型> <对象名> [,<对象类型> <对象名>]…

TO <用户> [,<用户>]…

[WITH GRANT OPTION];

其语义为:将对指定操作对象的指定操作权限授子指定的用户。发出该GRANT语句的可以是数据库管理员,也可以是该数据库对象创建者(即属主owner),还可以是已经拥有该权限的用户。接受权限的用户可以是一个或多个具体用户,也可以是PUBLIC,即全体用户。

如果指定了WITH GRANT OPTION子句,则获得某种权限的用户还可以把这种权限再授予其他的用户。如果没有指定WITH GRANT OPTION子句,则获得某种权限的用户只能使用该权限,不能传播该权限。

SQL标准允许具有WITH GRANT OPTION的用户把相应权限或其子集传递授子其他用户,但不允许循环授权,即被授权者不能把权限再授回给授权者或其祖先,如图4.4所示。

【例4.1】把查询Student表的权限授给用户U1。

GRANT SELECT

ON TABLE Student

TO U1;

【例4.2】把对Student表和Course表的全部操作权限授予用户U2和U3。

GRANT ALL PRIVILEGES

ON TABLE Student,Course

TO U2,U3;

【例4.3】把对表SC的查询权限授予所有用户。

GRANT SELECT

ON TABLE SC

TO PUBLIC;

【例4.4】把查询Student表和修改学生学号的权限授给用户U4。

GRANT UPDATE(Sno),SELECT

ON TABLE Student

TO U4;

这里,实际上要授予U4用户的是对基本表Student的SELECT权限和对属性列Sno的UPDATE权限。对属性列授权时必须明确指出相应的属性列名。

【例4.5】把对表SC的INSERT权限授予U5用户,并允许将此权限再授予其他用户。

GRANT INSERT

ON TABLE SC

TO U5

WITH GRANT OPTION;

执行此SQL语句后,U5不仅拥有了对表SC的INSERT权限,还可以传播此权限,即由U5用户发上述GRANT命令给其他用户。例如U5可以将此权限授予U6(例4.6)。

【例4.6】GRANT INSERT

ON TABLE SC

TO U6

WITH GRANT OPTION;

同样,U6还可以将此权限授予U7(例4.7)。

【例4.7】GRANT INSERT

ON TABLE SC

TO U7;

因为U6未给U7传播的权限,因此U7不能再传播此权限。

由上面的例子可以看到,GRANT语句可以一次向一个用户授权,如例4.1所示,这是最简单的一种授权操作;也可以一次向多个用户授权,如例4.2、4.3 所示;还可以一次传播多个同类对象的权限,如例4.2所示;甚至一次可以完成对基本表和属性列这些不同对象的授权,如例4.4所示。表4.4是执行了例4.1~4.7的语句后学生-课程数据库中的用户权限定义表。

《数据库系统概论》学习笔记_第16张图片

2.REVOKE

授予用户的权限可以由数据库管理员或其他授权者用REVOKE语句收回,REVOKE语句的一般格式为

REVOKE <权限> [,<权限>]…

ON <对象类型> <对象名> [,<对象类型><对象名>]…

FROM <用户> [,<用户>…[CASCADE|RESTRICT];

[例4.8] 把用户U4修改学生学号的权限收回。

REVOKE UPDATE(Sno)

ON TABLE Student

FROM U4;

【例4.9】收回所有用户对表SC的查询权限。

REVOKE SELECT

ON TABLE SC

FROM PUBLIC;

【例4.10】把用户U5对SC表的INSERT权限收回。

REVOKE INSERT

ON TABLE SC

FROM U5 CASCADE;

将用户U5的INSERT权限收回的同时,级联(CASCADE)收回了U6和U7的INSERT权限,否则系统将拒绝执行该命令。因为在例4.6中,U5将对SC表的INSERT权限授予了U6,而U6又将其授予了U7。

注意:这里默认值为CASCADE,有的数据库管理系统默认值为RESTRICT,将自动执行级联操作。如果U6或U7还从其他用户处获得对SC表的INSERT权限,则他们仍具有此权限,系统只收回直接或间接从U5处获得的权限。

SQL提供了非常灵活的授权机制。数据库管理员拥有对数据库中所有对象的所有权限,并可以根据实际情况将不同的权限授予不同的用户。

用户对自己建立的基本表和视图拥有全部的操作权限,并且可以用GRANT语句把其中某些权限授予其他用户。被授权的用户如果有“继续授权”的许可,还可以把获得的权限再授予其他用户。

所有授予出去的权力在必要时又都可以用REVOKE语句收回。

可见,用户可以“自主”地决定将数据的存取权限授予何人、决定是否也将“授权”的权限授予别人。因此称这样的存取控制是自主存取控制。

3.创建数据库模式的权限

GRANT和REVOKE语句向用户授予或收回对数据的操作权限。对创建数据库模式一类的数据库对象的授权则由数据库管理员在创建用户时实现。

CREATE USER语句般格式如下:

CREATE USER [WITH] [DBA | RESOURCE | CONNECT];

对CREATE USER语句说明如下:

●只有系统的超级用户才有权创建一个新的数据库用户。

●新创建的数据库用户有三种权限: CONNECT、RESOURCE和DBA。

●CREATE USER 命令中如果没有指定创建的新用户的权限,默认该用户拥有CONNECT权限。拥有CONNECT权限的用户不能创建新用户,不能创建模式,也不能创建基本表,只能登录数据库。由数据库管理员或其他用户授予他应有的权限,根据获得的授权情况他可以对数据库对象进行权限范围内的操作。

●拥有RESOURCE权限的用户能创建基本表和视图,成为所创建对象的属主,但不能创建模式,不能创建新的用户。数据库对象的属主可以使用GRANT语句把该对象上的存取权限授予其他用户。

●拥有DBA权限的用户是系统中的超级用户,可以创建新的用户、创建模式、创建基本表和视图等; DBA拥有对所有数据库对象的存取权限,还可以把这些权限授予一般用户。

以上说明可以用表4.6来总结。

表4.6 权限与可执行的操作对照表

拥有的权限

可否执行的操作

CREATE USER

CREATE SCHEMA

CREATE TABLE

登录数据库,执行数据查询和操纵

DBA

可以

可以

可以

可以

RESOURCE

不可以

不可以

可以

可以

CONNECT

不可以

不可以

不可以

可以,但必须拥有相应权限

注意:CREATE USER语句不是SQL标准,因此不同的关系数据库管理系统的语法和内容相差甚远。这里介绍该语句的目的是说明对于数据库模式这一类数据对象也有安全控制的需要,也是要授权的。

4.2.5 数据库角色

数据库角色是被命名的一组与数据库操作相关的权限,角色是权限的集合。因此,可以为一组具有相同权限的用户创建一个角色,使用角色来管理数据库权限可以简化授权的过程。

在SQL中首先用CREATE ROLE语句创建角色,然后用GRANT语句给角色授权,用REVOKE语句收回授予角色的权限。

1.角色的创建

创建角色的SQL语句格式是

CREATE ROLE <角色名>

刚刚创建的角色是空的,没有任何内容。可以用GRANT为角色授权。

2.给角色授权

GRANT <权限> [,<权限>]…

ON <对象类型>对象名

TO <角色> [,<角色>]…

数据库管理员和用户可以利用GRANT语句将权限授予某一个或几个角色。

3.将一个角色授予其他的角色或用户

GRANT <角色1>[,<角色2>]…

TO <角色3>[,<用户1>]…

[WITH ADMIN OPTION]

该语句把角色授予某用户,或授予另一个角色。这样,一个角色(例如角色3)所拥有的权限就是授予它的全部角色(例如角色1和角色2)所包含的权限的总和。

授予者或者是角色的创建者,或者拥有在这个角色上的ADMIN OPTION。

如果指定了WITH ADMIN OPTION子句,则获得某种权限的角色或用户还可以把这种权限再授予其他的角色。

一个角色包含的权限包括直接授予这个角色的全部权限加上其他角色授予这个角色的全部权限。

4.角色权限的收回

REVOKE <权限> [,<权限>]…

ON <对象类型> <对象名>

FROM <角色> [,<角色>]…

用户可以收回角色的权限,从而修改角色拥有的权限。

REVOKE动作的执行者或者是角色的创建者,或者拥有在这个(些)角色上的ADMIN OPTION。

【例4.11】通过角色来实现将一组权限授予一个用户。

步骤如下:

①首先创建一个角色R1。

CREATE ROLE R1;

②然后使用GRANT语句,使角色R1拥有Student表的SELECT、UPDATE、INSERT权限。

GRANT SELECT,UPDATE,INSERT

ON TABLE Student

TO R1;

③将这个角色授予王平、张明、赵玲,使他们具有角色R1所包含的全部权限。

GRANT R1

TO 王平,张明,赵玲;

④当然,也可以一次性地通过R1来收回王平的这三个权限。

REVOKE R1

FROM王平;

[例4.12] 角色的权限修改。

GRANT DELETE

ON TABLE Student

TO R1

使角色R1在原来的基础上增加了Student 表的DELETE权限。

[例4.13]

REVOKE SELECT

ON TABLE Student

FROM R1;

使R1减少了SELECT权限。

可以看出,数据库角色是一组权限的集合。使用角色来管理数据库权限可以简化授权的过程,使自主授权的执行更加灵活、方便。

4.2.6 强制存取控制方法

自主存取控制(MAC)能够通过授权机制有效地控制对敏感数据的存取。但是由于用户对数据的存取权限是“自主”的,用户可以自由地决定将数据的存取权限授予何人,以及决定是否也将“授权”的权限授予别人。在这种授权机制下,仍可能存在数据的“无意泄露”。比如,甲将自己权限范围内的某些数据存取权限授权给乙,甲的意图是仅允许乙本人操纵这些数据。但甲的这种安全性要求并不能得到保证,因为乙一旦获得了对数据的权限,就可以将数据备份,获得自身权限内的副本,并在不征得甲同意的前提下传播副本。造成这一问题的根本原因就在于,这种机制仅仅通过对数据的存取权限来进行安全控制,而数据本身并无安全性标记。要解决这一问题, 就需要对系统控制下的所有主客体实施强制存取控制策略。

所谓强制存取控制是指系统为保证更高程度的安全性,按照TDI/TCSEC标准中安全策略的要求所采取的强制存取检查手段。它不是用户能直接感知或进行控制的。强制存取控制适用于那些对数据有严格而固定密级分类的部门,例如军事部门或政府部门。

在强制存取控制中,数据库管理系统所管理的全部实体被分为主体和客体两大类。

主体是系统中的活动实体,既包括数据库管理系统所管理的实际用户,也包括代表用户的各进程。客体是系统中的被动实体,是受主体操纵的,包括文件、基本表、索引、视图等。对于主体和客体,数据库管理系统为它们每个实例(值)指派一个敏感度标记(label)。敏感度标记被分成若干级别,例如绝密(Top Secret, TS)、机密(Secret, S)、可信Confidential, C)、公开(Public, P)等。密级的次序是TS>=S>=C>= P。主体的敏感度标记称为许可证级别(clearance level),客体的敏感度标记称为密级(classification level)。强制存取控制机制就是通过对比主体的敏感度标记和客体的敏感度标记,最终确定主体是否能够存取客体。

当某一用户(或某一主体)以标记label注册入系统时,系统要求他对任何客体的存取必须遵循如下规则:

(1)仅当主体的许可证级别大于或等于客体的密级时,该主体才能读取相应的客体。

(2)仅当主体的许可证级别小于或等于客体的密级时,该主体才能写相应的客体。

规则(1)的意义是明显的,而规则(2)需要解释一下。按照规则(2), 用户可以为写入的数据对象赋予高于自己的许可证级别的密级。这样一旦数据被写入,该用户自己也不能再读该数据对象了。如果违反了规则(2), 就有可能把数据的密级从高流向低,造成数据的泄漏。例如,某个TS密级的主体把一个密级为TS的数据恶意地降低为P,然后把它写回。这样原来是TS密级的数据大家都可以读到了,造成了TS密级数据的泄漏。

强制存取控制是对数据本身进行密级标记,无论数据如何复制,标记与数据是一个不可分的整体,只有符合密级标记要求的用户才可以操纵数据,从而提供了更高级别的安全性。前面已经提到,较高安全性级别提供的安全保护要包含较低级别的所有保护,因此在实现强制存取控制时要首先实现自主存取控制(DAC),即自主存取控制与强制存取控制共同构成数据库管理系统的安全机制,如图4.5 所示。系统首先进行自主存取控制检查,对通过自主存取控制检查的允许存取的数据库对象再由系统自动进行强制存取控制检查,只有通过强制存取控制检查的数据库对象方可存取。

《数据库系统概论》学习笔记_第17张图片

4.3 视图机制

还可以为不同的用户定义不同的视图,把数据对象限制在一定的范围内。也就是说,通过视图机制把要保密的数据对无权存取的用户隐藏起来,从而自动对数据提供定程度的安全保护。

视图机制间接地实现支持存取谓词的用户权限定义。例如,在某大学中假定王平老师只能检索计算机系学生的信息,系主任张明具有检索和增删改计算机系学生信息的所有权限。这就要求系统能支持“存取谓词”的用户权限定义。在不直接支持存取谓词的系统中,可以先建立计算机系学生的视图CS_ Student, 然后在视图上进一步定义存取权限。

[例4.14] 建立计算机系学生的视图,把对该视图的SELECT权限授予王平,把该视图上的所有操作权限授子张明。

CREATE VIEW CS_Student /*先建立视图CS_Student*/

AS

SELECT *

FROM Student

WHERE Sdept='CS';

GRANT SELECT /*王平老师只能检索计算机系学生的信息*/

ON CS_Student

TO 王平;

GRANT ALL PRIVILEGES /*系主任具有检索和删改计算机系学生信息的所有权限*/

ON CS_Student

TO 张明;

4.4 审计

前面讲的用户身份鉴别、存取控制是数据库安全保护的重要技术(安全策略方面),但不是全部。为了使数据库管理系统达到一定的安全级别,还需要在其他方面提供相应的支持。例如按照TDI/TCSEC标准中安全策略的要求,审计(audit)功能就是数据库管理系统达到C2以上安全级别必不可少的一项指标。

因为任何系统的安全保护措施都不是完美无缺的,蓄意盗窃、破坏数据的人总是想方设法打破控制。审计功能把用户对数据库的所有操作自动记录下来放入审计日志(audit log)中。审计员可以利用审计日志监控数据库中的各种行为,重现导致数据库现有状况的一系列事件,找出非法存取数据的人、时间和内容等。还可以通过对审计日志分析,对潜在的威胁提前采取措施加以防范。

审计通常是很费时间和空间的,所以数据库管理系统往往都将审计设置为可选特征,允许数据库管理员根据具体应用对安全性的要求灵活地打开或关闭审计功能。审计功能主要用于安全性要求较高的部门。

可审计事件有服务器事件、系统权限、语句事件及模式对象事件,还包括用户鉴别、自主访问控制和强制访问控事件。换句话说,它能对普通和特权用户行为、各种表操作、身份鉴别、自主和强制访问控制等操作进行审计。它既能审计成功操作,也能审计失败操作。

1.审计事件

审计事件一般有多个类别,例如,

●服务器事件:审计数据库服务器发生的事件,包含数据库服务器的启动、停止、数据库服务器配置文件的重新加载。

●系统权限:对系统拥有的结构或模式对象进行操作的审计,要求该操作的权限是通过系统权限获得的。

●语句事件:对SQL语句,如DDL、DML、DQL (Data Query Language,数据查询语言)及DCL语句的审计。

●模式对象事件:对特定模式对象上进行的SELECT或DML操作的审计。模式对象包括表、视图、存储过程、函数等。模式对象不包括依附于表的索引、约束、触发器、分区表等。

2.审计功能

审计功能主要包括以下几方面内容:

●基本功能,提供多种审计查阅方式:基本的、可选的、有限的,等等。

●提供多套审计规则,审计规则-般在数据库初始化时设定,以方便审计员管理。

●提供审计分析和报表功能。

●审计日志管理功能,包括为防止审计员误删审计记录,审计日志必须先转储后删除;对转储的审计记录文件提供完整性和保密性保护;只允许审计员查阅和转储审计记录,不允许任何用户新增和修改审计记录;等等。

●系统提供查询审计设置及审计记录信息的专门视图。对于系统权限级别、语句级别及模式对象级别的审计记录也可通过相关的系统表直接查看。

3. AUDIT语句和NOAUDIT语句

AUDIT语句用来设置审计功能,NOAUDIT语句则取消审计功能。

审计一般可以分为用户级审计和系统级审计。用户级审计是任何用户可设置的审计,主要是用户针对自己创建的数据库表或视图进行审计,记录所有用户对这些表或视图的一切成功和(或)不成功的访问要求以及各种类型的SQL操作。

系统级审计只能由数据库管理员设置,用以监测成功或失败的登录要求、监测授权和收回操作以及其他数据库级权限下的操作。

[例4.15] 对修改SC表结构或修改SC表数据的操作进行审计。

AUDIT ALTER, UPDATE

ON SC;

[例4.16] 取消对SC表的一切审计。

NOAUDIT ALTER, UPDATE

ON SC;

审计设置以及审计日志一般都存储在数据字典中。必须把审计开关打开(即把系统参数audit_trail 设为true),才可以在系统表SYS_AUDITTRAIL中查看到审计信息。

数据库安全审计系统提供了一种事后检查的安全机制。安全审计机制将特定用户或者特定对象相关的操作记录到系统审计日志中,作为后续对操作的查询分析和追踪的依据。通过审计机制,可以约束用户可能的恶意操作。

4.5 数据加密

对于高度敏感性数据,例如财务数据、军事数据、国家机密数据等,除前面介绍的安全性措施外,还可以采用数据加密技术。数据加密是防止数据库数据在存储和传输中失密的有效手段。加密的基本思想是根据一定的算法将原始数据——明文 (plain text) 变换为不可直接识别的格式——密文(cipher text),从而使得不知道解密算法的人无法获知数据的内容。

数据加密主要包括存储加密和传输加密。

1.存储加密

对于存储加密,一般提供透明和非透明两种存储加密方式。透明存储加密是内核级加密保护方式,对用户完全透明;非透明存储加密则是通过多个加密函数实现的。

透明存储加密是数据在写到磁盘时对数据进行加密,授权用户读取数据时再对其进行解密。由于数据加密对用户透明,数据库的应用程序不需要做任何修改,只需在创建表语句中说明需加密的字段即可。当对加密数据进行增、删、改、查询操作时,数据库管理系统将自动对数据进行加、解密工作。基于数据库内核的数据存储加密、解密方法性能较好,安全完备性较高。

2.传输加密

在客户/服务器结构中,数据库用户与服务器之间若采用明文方式传输数据,容易被网络恶意用户截获或篡改,存在安全隐患。因此,为保证二者之间的安全数据交换,数据库管理系统提供了传输加密功能。

常用的传输加密方式如链路加密和端到端加密。其中,链路加密对传输数据在链路层进行加密,它的传输信息由报头和报文两部分组成,前者是路由选择信息,而后者是传送的数据信息。这种方式对报文和报头均加密。相对地,端到端加密对传输数据在发送端加密,接收端解密。它只加密报文,不加密报头。与链路加密相比,它只在发送端和接收端需要密码设备,而中间节点不需要密码设备,因此它所需密码设备数量相对较少。但这种方式不加密报头,从而容易被非法监听者发现并从中获取敏感信息。

图4.6是一种基于基于安全套接层协议(Security Socket Layer, SSL)的数据库管理系统可信传输方案。它采用的是一种端到端的传输加密方式。在这个方案中,通信双方协商建立可信连接,一次会话采用一个密钥,传输数据在发送端加密,接收端解密,有效降低了重放攻击和恶意篡改的风险。此外,出于易用性考虑,这个方案的通信加密还对应用程序透明。它的实现思路包含以下三点。

《数据库系统概论》学习笔记_第18张图片

(1)确认通信双方端点的可靠性

数据库管理系统采用基于数字证书的服务器和客户端认证方式实现通信双方的可靠性确认。用户和服务器各自持有由知名数字证书认证(Certificate Authority, CA)中心或企业内建CA颁发的数字证书,双方在进行通信时均首先向对方提供己方证书,然后使用本地的CA信任列表和证书撤销列表(Certificate Revocation List, CRL)对接收到的对方证书进行验证,以确保证书的合法性和有效性,进而保证对方确系通信的目的端。

(2)协商加密算法和密钥

确认双方端点的可靠性后,通信双方协商本次会话的加密算法与密钥。在这个过程中,通信双方利用公钥基础设施(Public Key Infrastructure, PKI)方式保证了服务器和客户端的协商过程通信的安全可靠。

(3)可信数据传输

在加密算法和密钥协商完成后,通信双方开始进行业务数据交换。与普通通信路径不同的是,这些业务数据在被发送之前将被用某一组特定的密钥进行加密和消息摘要计算,以密文形式在网络上传输。当业务数据被接收的时候,需用相同一组特定的密钥进行解密和摘要计算。所谓特定的密钥,是由先前通信双方磋商决定的,为且仅为双方共享,通常称之为会话密钥。第三方即使窃取传输密文,因无会话密钥也无法识别密文信息。一旦第三方对密文进行任何篡改,均将会被真实的接收方通过摘要算法识破。另外,会话密钥的生命周期仅限于本次通信,理论上每次通信所采用的会话密钥将不同,因此避免了使用固定密钥而引起的密钥存储类问题。

数据库加密使用已有的密码技术和算法对数据库中存储的数据和传输的数据进行保护。加密后数据的安全性能够进一步提高。即使攻击者获取数据源文件,也很难获取原始数据。但是,数据库加密增加了查询处理的复杂性,查询效率会受到影响。加密数据的密钥的管理和数据加密对应用程序的影响也是数据加密过程中需要考虑的问题。

4.6 其他安全性保护

为满足较高安全等级数据库管理系统的安全性保护要求,在自主存取控制和强制存取控制之外,还有推理控制以及数据库应用中隐蔽信道和数据隐私保护等技术。

推理控制(inference control)处理的是强制存取控制未解决的问题。例如,利用列的函数依赖关系,用户能从低安全等级信息推导出其无权访问的高安全等级信息,进而导致信息泄露。

数据库推理控制机制用来避免用户利用其能够访问的数据推知更高密级的数据,即用户利用其被允许的多次查询的结果,结合相关的领域背景知识以及数据之间的约束,推导出其不能访问的数据。在推理控制方面,常用的方法如基于函数依赖的推理控制和基于敏感关联的推理控制等。例如,某个公司信息系统中假设姓名和职务属于低安全等级(如公开)信息,而工资属于高安全等级(如机密)信息。用户A的安全等级较低,他通过授权可以查询自己的工资、姓名、职务,及其他用户的姓名和职务。由于工资是机密信息,因此用户A不应知道其他用户的工资。但是,若用户B的职务和用户A相同,则利用函数依赖关系职务>工资,用户A可通过自己的工资信息(假设3000元),推出B的工资也是3000元,从而导致高安全等级的敏感信息泄露。

隐蔽信道(covertchannal)处理内容也是强制存取控制未解决的问题。下面的例子就是利用未被强制存取控制的SQL执行后反馈的信息进行间接信息传递。

通常,如果insert语句对unique属性列写入重复值,则系统会报错且操作失败。那么,针对unique约束列,高安全等级用户(发送者)可先向该列插入(或者不插入)数据,而低安全等级用户(接收者)向该列插入相同数据。

如果插入失败,则表明发送者已向该列插入数据,此时二者约定发送者传输信息位为0;如果插入成功,则表明发送者未向该列插入数据,此时二者约定发送者传输信息位为1。通过这种方式,高安全等级用户按事先约定方式主动向低安全等级用户传输信息,使得信息流从高安全等级向低安全等级流动,从而导致高安全等级敏感信息泄露。

随着人们对隐私的重视,数据隐私(data privacy)成为数据库应用中新的数据保护模式。

所谓数据隐私是控制不愿被他人知道或他人不便知道的个人数据的能力。数据隐私范围很广,涉及数据管理中的数据收集、数据存储、数据处理和数据发布等各个阶段。例如,在数据存储阶段应避免非授权的用户访问个人的隐私数据。通常可以使用数据库安全技术实现这一阶段的隐私保护。如使用自主访问控制、强制访问控制和基于角色的访问控制以及数据加密等。在数据处理阶段,需要考虑数据推理带来的隐私数据泄露。非授权用户可能通过分析多次查询的结果,或者基于完整性约束信息,推导出其他用户的隐私数据。在数据发布阶段,应使包含隐私的数据发布结果满足特定的安全性标准。如发布的关系数据表首先不能包含原有表的候选码,同时还要考虑准标识符的影响。

准标识符是能够唯一确定大部分记录的属性集合。在现有安全性标准中,k-匿名化(k-anonymization)标准要求每个具有相同准标识符的记录组中至少包括k条记录,从而控制攻击者判别隐私数据所属个体的概率。还有l-多样化标准(l-diversity)、 t-临近标准(t-closeness)等,从而使攻击者不能从发布数据中推导出额外的隐私数据。数据隐私保护也是当前研究的热点。

要想万无一失地保证数据库安全,使之免于遭到任何蓄意的破坏几乎是不可能的。但高度的安全措施将使蓄意的攻击者付出高昂的代价,从而迫使攻击者不得不放弃他们的破坏企图。

第5章 数据库完整性

数据库的完整性(integrity)是指数据的正确性(correctness)和相容性(compatability)。数据的正确性是指数据是符合现实世界语义、反映当前实际状况的;数据的相容性是指数据库同一对象在不同关系表中的数据是符合逻辑的。

例如,学生的学号必须唯一,性别只能是男或女,本科学生年龄的取值范围为14~50的整数,学生所选的课程必须是学校开设的课程,学生所在的院系必须是学校已成立的院系等。

数据的完整性和安全性是两个既有联系又不尽相同的概念。数据的完整性是为了防止数据库中存在不符合语义的数据,也就是防止数据库中存在不正确的数据。数据的安全性是保护数据库防止恶意破坏和非法存取。因此,完整性检查和控制的防范对象是不合语义的、不正确的数据,防止它们进入数据库。安全性控制的防范对象是非法用户和非法操作,防止他们对数据库数据的非法存取。

为维护数据库的完整性,数据库管理系统必须能够实现如下功能。

1.提供定义完整性约束条件的机制

完整性约束条件也称为完整性规则,是数据库中的数据必须满足的语义约束条件。它表达了给定的数据模型中数据及其联系所具有的制约和依存规则,用以限定符合数据模型的数据库状态以及状态的变化,以保证数据的正确、有效和相容。SQL标准使用了一系列概念来描述完整性,包括关系模型的实体完整性、参照完整性和用户定义完整性。这些完整性一般由SQL的数据定义语言语句来实现,它们作为数据库模式的一部分存 入数据字典中。

2.提供完整性检查的方法

数据库管理系统中检查数据是否满足完整性约束条件的机制称为完整性检查。一般在INSERT、UPDATE、DELETE语句执行后开始检查,也可以在事务提交时检查。检查这些操作执行后数据库中的数据是否违背了完整性约束条件。

3.进行违约处理

数据库管理系统若发现用户的操作违背了完整性约束条件将采取一定的动作,如拒绝(NO ACTION)执行该操作或级联(CASCADE)执行其他操作,进行违约处理以保证数据的完整性。

早期的数据库管理系统不支持完整性检查,因为完整性检查费时费资源。现在商用的关系数据库管理系统产品都支持完整性控制,即完整性定义和检查控制由关系数据库管理系统实现,不必由应用程序来完成,从而减轻了应用程序员的负担。更重要的是,关系数据库管理系统使得完整性控制成为其核心支持的功能,从而能够为所有用户和应用提供一致的数据库完整性。因为由应用程序来实现完整性控制是有漏洞的,有的应用程序定义的完整性约束条件可能被其他应用程序破坏,数据库数据的正确性仍然无法保障。

第2章2.3节关系的完整性已经讲解了关系数据库三类完整性约束的基本概念,下面将介绍SQL语言中实现这些完整性控制功能的方法。

5.1 实体完整性

5.1.1 定义实体完整性

关系模型的实体完整性在CREATE TABLE中用PRIMARY KEY定义。对单属性构成的码有两种说明方法,一种是定义为列级约束条件,另一种是定义为表级约束条件。对多个属性构成的码只有一种说明方法,即定义为表级约束条件。

以下部分插播三级数据库技术教程:

第7章 数据库及数据库对象

7.1 创建及维护数据库

数据库是存储数据及各种数据库对象的容器,在介绍其他数据库对象之前,本节首先介绍数据库的创建及维护方法。

7.1.1 SQL Server数据库概述

从数据库的应用和管理角度,SQL Server将数据库分为两大类:系统数据库和用户数据库。系统数据库是SQL Server数据库管理系统自动创建和维护的,这些数据库用于保存维护系统正常运行的信息,例如,一个SQL Server实例上共建有多少个数据库,每个数据库的属性及其所含的对象,每个数据库的用户以及用户的权限等。用户数据库保存的是与用户的业务有关的数据,通常所说的建立数据库指的是创建用户数据库,对数据库的维护也指的是对用户数据库的维护。一般用户对系统数据库只有查询权。

安装好SQL Server后,系统会自动安装五个系统数据库,分别是:master, msdb, model, tempdb和Resourse,各数据库的主要用途如下:

  • master:是SQL Server中最重要的数据库,记录SQL Server实例的所有系统级信息,包括实例范围的元数据(例如登录账户)、端点、连接服务器和系统配置设置。另外,master数据库还记录了所有其他数据库的存在、数据库文件的位置以及SQL Server的初始化信息。

  • msdb:供SQL Server代理服务调度报警和作业以及记录操作员时使用,保存关于调度报警、作业、操作员等信息,作业是SQL Server中定义的自动执行的一系列操作的集合,作业的执行不需要任何人工干预。

  • model:用作SQL Server实例上创建的所有数据库的模板。对model数据库进行的修改(如数据库大小、排列规则、恢复模式和其他数据库选项)将应用于以后创建的所有用户数据库。当用户创建一个数据库时,系统自动将model数据库中的全部内容复制到新建数据库中。

  • tempdb:临时数据库,用于保存临时对象或中间结果集,并为数据的排序等操作提供一个临时工作空间。每次启动SQL Server时都会重新创建tempdb数据库。

  • Resourse:是一个只读数据库,包含了SQL Server中的所有系统对象。SQL Server系统对象在物理上保存在Resourse数据库中,但在逻辑上却显示在每个数据库的sys架构中。因此,在SSMS的对象资源管理器中,在“系统数据库”下看不到这个数据库。

7.1.2 SQL Server数据库的组成

SQL Server将数据库映射为一组操作系统文件,这些文件被划分为两类:数据文件和日志文件。数据文件包含数据和对象,日志文件包含恢复数据库中的所有事务需要的信息。

1.数据文件

数据文件用于存放数据库数据。数据文件又分为主要数据文件和次要数据文件。

  • 主要数据文件。主要数据文件的推荐扩展名是.mdf,它包含数据库的系统信息,也可存放用户数据。每个数据库都有且只能有一个主要数据文件。主要数据文件是为数据库创建的一个数据文件。SQL Server 2008要求主要数据文件的大小不能小于3MB。

  • 次要数据文件。次要数据文件的推荐扩展名是.ndf。一个数据库可以不包含次要数据文件,也可以包含多个次要数据文件,而且这些次要数据文件可以建立在一个磁盘上,也可以分别建立在不同的磁盘上。

当某个数据库包含的数据量比较大,需要占用较大的磁盘空间时,就可以为数据库创建多个次要数据文件,以使每个文件建立在不同的磁盘上。在主要数据文件之后建立的所有数据文件都是次要数据文件。

次要数据文件的使用和主要数据文件的使用对用户来说是没有区别的,对用户也是透明的,用户无须关心自己的数据是存放在主要数据文件上还是次要数据文件上。

让一个数据库包含多个数据文件,并且让这些数据文件分别建立在不同的磁盘上,不仅有利于充分利用多个磁盘上的存储空间,而且可以提高数据的存取效率。

2.事务日志文件

事务日志文件的推荐扩展名为.ldf,用于存放恢复数据库的所有日志信息。每个数据库必须至少有一个日志文件,也可以有多个日志文件。

SQL Server 2008不强制使用上述文件扩展名,但建议使用这些扩展名以利于标识文件的用途。

3.数据库存储空间的分配

在创建数据库时,了解SQL Server如何存储数据是很有必要的,这样可以比较准确地估算出数据库需占用的空间大小以及如何为数据文件和日志文件分配磁盘空间。

在考虑数据库的空间分配时,需了解如下规则:

  • 在创建用户数据库时,model数据库自动被复制到新建用户数据库中,而且是复制到主要数据文件中。

  • 在SQL Server 2008中,数据的存储分配单位是数据页(Page,也简称为页)。一页是一块8KB(8×1024B,其中用8060B存放数据,另外的132B存放系统信息)的连续磁盘空间。页是存储数据的最小单位,页的大小决定了数据库表中一行数据的最大大小。

  • SQL Server不允许表中的一行数据存储在不同页上[varchar(max)、nvarchar(max)、text、ntext、varbinary(max)和image数据类型除外],即行不能跨页存储。因此表中一行数据的大小不能超过8060B。这意味着在设计关系表时要考虑每行数据的大小,以提高空间利用率。

根据一行数据不能跨页存储、一个表中包含的数据行数以及每行占用的字节数,可以估算出一个数据表所需占用的大致空间。例如,假设一个数据表有10000行数据,每行3000字节,每个数据页可存放两行数据,则此表需要的空间为:(10000/2)×8KB=40MB。其中,每页中有6000B用于存储数据,有2060B是浪费的。因此该数据表的空间大约浪费25%。

7.1.3 数据库文件组

文件组的概念类似于操作系统当中的文件夹,在操作系统中,为便于对文件进行管理,可以定义一些文件夹,然后将不同的文件放置到不同的文件夹中。在数据库中,可以定义多个文件组,然后将文件放置到不同的文件组中。

SQL Server有两种类型的文件组:主文件组和用户定义的文件组。

1.主文件组

主文件组(PRIMARY)是系统定义好的一个文件组,它包含主要数据文件和任何没有明确分配给其他文件组的其他数据文件。系统表的所有页均分配在主文件组中。

2.用户定义文件组

用户可以创建自己的文件组,以将数据文件组织起来,便于管理和数据分配。例如,可以分别在三个磁盘驱动器上创建三个文件Data1.ndf, Data2.ndf和Data3.ndf,然后将它们分配到文件组fgroup1上,之后就可以明确地在文件组fgroup1上创建新表,而对表中数据的查询将分散到三个磁盘上,从而提高数据查询性能。用户定义文件组是通过在CREATE DATABASE或ALTER DATABASE语句中使用FILEGROUP关键字指定的任何文件组。

说明:

(1)日志文件不包括在文件组内,日志空间与数据空间是分开管理的。

(2)一个文件不可以是多个文件组的成员。

(3)如果文件组中有多个文件,则他们在所有文件被填满之前不会自动增长,而填满后这些文件会循环增长。

如果在定义数据文件时没有指定其所属的文件组,则新建数据文件将被分配到默认文件组。每个数据库只能制定一个文件组为默认文件组。如果用户没有显式地用ALTER DATABASE语句修改默认文件组,则SQL Server的默认文件组是PRIMARY。

在SQL Server 2008中,可以在首次创建数据库时创建文件组,也可以在以后向数据库中添加更多数据文件时创建文件组。但是,一旦将文件添加到数据库中,就不能再将这些文件移到其他文件组中。

7.1.4 数据库文件的属性

在定义数据库时,除了指定数据库的名字之外,其余要做的工作就是定义数据库的数据文件和日志文件,定义这些文件需要指定的信息包括:

1.文件名及其位置

数据库的每个数据文件和日志文件都具有一个逻辑文件名和物理文件名。逻辑文件名是在所有T-SQL语句中引用物理文件时所使用的名称,该文件名必须符合SQL Server标识符规则,而且在一个数据库中逻辑文件名必须是唯一的。物理文件名包括存储文件的路径和物理磁盘文件名,该文件名必须符合操作系统文件命名规则。一般情况下,如果有多个数据文件的话,为了获得更好的性能,建议将文件分散存储在多个物理磁盘上。

2.初始大小

可以指定每个数据文件和日志文件的初始大小。在指定主要数据文件的初始大小时,其大小不能小于model数据库主要数据文件的大小,因为系统是将model数据库主要数据文件的内容复制到用户数据库的主要数据文件上。

3.增长方式

如果需要的话,可以指定文件是否自动增长。该选项的默认配置为自动增长,即当数据文件的空间不足后,系统自动扩大文件空间,这样可以防止由于空间用完而造成的不能插入新数据或不能进行数据操作的错误。

4.最大大小

文件的最大大小指的是文件增长的最大空间限制。默认情况是无限制。建议用户设定允许文件增长的最大空间大小,因为如果用户不设定最大空间大小,但设置了文件自动增长方式,则文件将会无限制增长直到磁盘空间用完为止。

现在,我们回到《数据库系统概论》一书中,回到第8章数据库编程来继续学习下面的内容。

第8章 数据库编程

标准SQL是非过程化的查询语言,具有操作统一、面向集合、功能丰富、使用简单等多项优点。但和程序设计语言相比,高度非过程化的优点也造成了它的一个弱点:缺少流程控制能力,难以实现应用业务中的逻辑控制。SQL编程技术可以有效克服SQL语言实现复杂应用方面的不足,提高应用系统和数据库管理系统间的互操作性。

8.1 嵌入式SQL

8.1.1 嵌入式SQL的处理过程

嵌入式SQL是将SQL语句嵌入程序设计语言中,被嵌入的程序设计语言,如C、C++、Java等称为宿主语言,简称主语言。

对嵌入式SQL,数据库管理系统般采用预编译方法处理,即由数据库管理系统的预处理程序对源程序进行扫描,识别出嵌入式SQL语句,把它们转换成主语言调用语句,以使主语言编译程序能识别它们,然后由主语言的编译程序将纯的主语言程序编译成目标码。

《数据库系统概论》学习笔记_第19张图片

在嵌入式SQL中,为了能快速区分SQL语句与主语言语句,所有SQL语句都必须加前缀。当主语言为C语言时,语法格式为

EXEC SQL

本书使用这个语法格式。

如果主语言为Java,则嵌入式SQL称为SQLJ,语法格式为

#SQL {};

8.1.2 嵌入式SQL语句与主语言之间的通信

将SQL嵌入到高级语言中混合编程,SQL语句负责操纵数据库,高级语言语句负责控制逻辑流程。这时程序中会含有两种不同计算模型的语句,它们之间应该如何通信呢?

数据库工作单元与源程序工作单元之间的通信主要包括:

(1)向主语言传递SQL语句的执行状态信息,使主语言能够据此信息控制程序流程,主要用SQL通信区(SQL Communication Aera, SQLCA)实现。

(2)主语言向SQL语句提供参数,主要用主变量实现。

(3)将SQL语句查询数据库的结果交主语言处理,主要用主变量和游标(cursor)实现。

1.SQL通信区

SQL语句执行后,系统要反馈给应用程序若干信息,主要包括描述系统当前工作状态和运行环境的各种数据。这些信息将送到SQL通信区中,应用程序从SQL通信区中取出这些状态信息,据此决定接下来执行的语句。

SQL通信区在应用程序中用EXEC SQL INCLUDE SQLCA加以定义。SQL通信区中有一个变量SQLCODE,用来存放每次执行SQL语句后返回的代码。

应用程序每执行完一条SQL语句之后都应该测试一下SQLCODE的值,以了解该SQL语句执行情况并做相应处理。如果SQLCODE等于预定义的常量SUCCESS,则表示SQL语句成功,否则在SQLCODE存放错误代码。程序员可以根据错误代码查找问题。

2.主变量

嵌入式SQL语句中可以使用主语言的程序变量来输入或输出数据。SQL语句中使用的主语言程序变量简称为主变量。主变量根据其作用的不同分为输入主变量和输出主变量。输入主变量由应用程序对其赋值,SQL语句引用;输出主变量由SQL语句对其赋值或设置状态信息,返回给应用程序。

一个主变量可以附带一个任选的指示变量。指示变量是一个整型变量,用来“指示”所指主变量的值或条件。指示变量可以指示输入主变量是否为空值,可以检测输出主变量是否为空值,值是否被截断。

所有主变量和指示变量必须在SQL语句BEGIN DECLARE SECTION 与END DECLARE SECTION之间进行说明。说明之后,主变量可以在SQL语句中任何一个能够使用表达式的地方出现,为了与数据库对象名(表名、视图名、列名等)区别,SQL语句中的主变量名和指示变量前要加冒号(:)作为标志。

3.游标

SQL是面向集合的,一条SQL语句可以产生或处理多条记录;而主语言是面向记录的,一组主变量一次只能存放一条记录。所以仅使用主变量并不能完全满足SQL语句向应用程序输出数据的要求,为此嵌入式SQL引入了游标的概念,用游标来协调这两种不同的处理方式。

游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果,每个游标区都有一个名字。用户可以通过游标逐一获取记录并赋给主变量,交由主语言进一步处理。

4.建立和关闭数据库连接

嵌入式SQL程序要访问数据库必须先连接数据库,关系数据库管理系统根据用户信息对连接请求进行合法性验证,只有通过了身份验证,才能建立一个可用的合法连接。

(1)建立数据库连接

建立连接的嵌入式SQL语句是

EXEC SQL CONNECT TO target[AS connection-name][USER user-name];

其中:

target是要连接的数据库服务器,它可以是一个常见的服务器标识串,如@:,可以是包含服务器标识的SQL串常量,也可以是DEFAULT。

connection-name是可选的连接名,连接名必须是一个有效的标识符,主要用来识别一个程序内同时建立的多个连接,如果在整个程序内只有一个连接,也可以不指定连接名。

如果程序运行过程中建立了多个连接,执行的所有数据库单元的工作都在该操作提交时所选择的当前连接上。程序运行过程中可以修改当前连接,对应的嵌入式SQL语句为:

EXEC SQL SET CONNECTION connection-name|DEFAULT;

(2)关闭数据库连接

当某个连接上的所有数据库操作完成后,应用程序应该主动释放所占用的连接资源。关闭数据库连接的嵌入式SQL语句是:

EXEC SQL DISCONNECT [connection];

其中,connection是EXEC SQL CONNECT所建立的数据库连接。

5.程序实例

【例8.1】依次检查某个系的学生记录,交互式更新某些学生年龄。

EXEC SQL BEGIN DECLARE SECTION; /*主变量说明开始*/

char deptname[20];

char hsno[9];

char hsname[20];

char hssex[2];

int HSage;

int NEWAGE;

EXEC SQL END DECLARE SECTION; /*主变量说明结束*/

long SQLCODE;

EXEC SQL INCLUDE SQLCODE; /*定义SQL通信区*/

int main(void) /*C语言主程序开始*/

{

int count=0;

char yn;

printf("Please choose the department name(CS/MA/IS):");

scanf("%s",&deptname);

EXEC SQL CONNECT TO TEST@localhost:54321 USER "SYSTEM"/"MANAGER";

EXEC SQL DECLARE SX CURSOR FOR

SELECT Sno,Sname,Ssex,Sage

FROM Student

WHERE SDept=:deptname;

EXEC SQL OPEN SX;

for(; ;)

{

EXEC SQL FETCH SX INTO:HSno,:Sname,:HSex,:HSage;

if (SQLCA.SQLCODE!=0)

/* SQLCODE !=0,表示操作不成功*/

break;

/*利用SQLCA中的状态信息决定何时退出循环*/

if(count++==0)

/*如果是第-一行的话,先打出行头*/

printf("n%- 10s %-20s %- 10s %- 10sln" "Sno" ,"Sname","sex","Sage"); Daga

printf("%-10s %-20s %-10s %- 10dn",HSno,HSname,HSsex,HSage);

/*打印查询结果*/

printf("UPDATE AGE(y/n)?);面个时出治 6 /*询问用户是否要更新该学生的年龄*/

do{ scanf("%c",&yn);

while(yn!='N' && yn!='n' && yn!="'Y' && yn!='y);

if(yn=='y'||yn=="Y')

/*如果选择更新操作*/qs6b

{ printf("INPUT NEW AGE:");

scanf("%d" &NEWAGE);

/*用户输入新年龄到主变量中*/

EXEC SQL UPDATE Student

/*嵌入式SQL更新语句*/

SET Sage=:NEWAGE

WHERE CURRENT OF SX; /*对 当前游标指向的学生年龄进行更新*/

}

EXEC SQL CLOSE SX;

/*关闭游标SX,不再和查询结果对应*/

EXEC SQL COMMIT WORK;

/*提交更新*/

EXEC SQL DISCONNECT TEST;

/*断开数据库连接*/

}

8.1.3 不用游标的SQL语句

有的嵌入式SQL语句不需要使用游标,它们是说明性语句、数据定义语句、数据控制语句、查询结果为单记录的SELECT语句、非CURRENT形式的增删改语句。

1.查询结果为单记录的SELECT语句

这类语句因为查询结果只有一个,只需用INTO子句指定存放查询结果的主变量,不需要使用游标。

[例8.2]根据学生号码查询学生信息。

EXEC SQL SELECT Sno,Sname,Ssex,Sage,Sdept

INTO :Hsno,:Hname;Hsex;:Hage;Hdept

FROM Student

WHERE Sno=:givensno;

/*把要查询的学生的学号赋给了主变量givensno*/

使用查询结果为单记录的SELECT语句需要注意以下几点:

(1) INTO 子句、WHERE子句和HAVING短语的条件表达式中均可以使用主变量。

(2)查询结果为空值的处理。查询返回的记录中可能某些列为空值NULL.为了表示空值,在INTO子句的主变量后面跟有指示变量,当查询得出的某个数据项为空值时,系统会自动将相应主变量后面的指示变量置为负值,而不再向该主变量赋值。所以当指示变量值为负值时,不管主变量为何值,均认为主变量值为NULL。

(3)如果查询结果实际上并不是单条记录,而是多条记录,则程序出错,关系数据库管理系统会在SQL通信区中返回错误信息。

[例8.3]查询某个学生选修某门课程的成绩。假设已经把将要查询的学生的学号赋给了主变量givensno, 将课程号赋给了主变量givencno.

EXEC SQL SELECT Sno,Cno,Grade

INTO :Hsno, :Hcno, :Hgrade:Gradeid

/*指示变量Gradeid*/

FROM SC

WHERE Sno=:givensno AND Cno=:givencno;

如果Gradeid<0,则不论Hgrade为何值均认为该学生成绩为空值。

2.非CURRENT形式的增删改语句

有些非CURRENT形式的增删改语句不需要使用游标。在UPDATE的SET子句和WHERE子句中可以使用主变量,SET子句还可以使用指示变量。

[例8.4]修改某个学生选修 1号课程的成绩。

EXEC SQL UPDATE SC

SET Grade=:newgrade

/*修改的成绩已赋给主变量: newgrade */

WHERE Sno givensno and Cno=1; /*学号已赋给主变量: givensno*/

[例8.5]某个学生新选修了某门课程,将有关记录插入SC表中。假设插入的学号已赋给主变量stdno,课程号已赋给主变量couno,由于该学生刚选修课程,成绩应为空,所以要把指示变量赋为负值。

gradeid= 1;

/*gradeid为指示变量,赋为负值*/

EXEC SQL INSERT

INTO SC(Sno,Cno,Grade)

VALUES(:stdno,couno,gr :gradeid);

/*:stdno, :couno, :gr 为主变量*/

8.1.4 使用游标的SQL语句

必须使用游标的SQL语句有查询结果为多条记录的SELECT语句、CURRENT形式的UPDATE和DELETE语句。

1.查询结果为多条记录的SELECT语句

一般情况下,SELECT语句查询结果是多条记录,因此需要用游标机制将多条记录次一条地送主程序处理,从而把对集合的操作转换为对单个记录的处理。使用游标的步骤为:

(1)说明游标

用DECLARE语句为一条SELECT语句定义游标:

EXEC SQL DECLARE <游标名> CURSOR FOR ;

定义游标仅仅是一条说明性语句,这时关系数据库管理系统并不执行 SELECT语句。

(2)打开游标

用OPEN语句将定义的游标打开。

EXEC SQL OPEN <游标名>;

打开游标实际上是执行相应的SELECT语句,把查询结果取到缓冲区中。这时游标处于活动状态,指针指向查询结果集中的第一条记录。

(3)推进游标指针并取当前记录

EXEC SQL FETCH <游标名>

INTO <主变量>[<指示变量>][,<主变量>[<指示变量>]]...;

其中主变量必须与SELECT语句中的目标列表达式具有一一对应关系。

用FETCH语句把游标指针向前推进一条记录,同时将缓冲区中的当前记录取出来送至主变量供主语言进一步处理。通过循环执行FETCH语句逐条取出结果集中的行进行处理。

(4)关闭游标

用CLOSE语句关闭游标,释放结果集占用的缓冲区及其他资源。

EXEC SQL CLOSE <游标名>;

游标被关闭后就不再和原来的查询结果集相联系。但被关闭的游标可以再次被打开,与新的查询结果相联系。

2. CURRENT形式的UPDATE和DELETE语句

UPDATE语句和DELETE语句都是集合操作,如果只想修改或删除其中某个记录,则需要用带游标的SELECT语句查出所有满足条件的记录,从中进一步找出要修改或删除的记录,然后用CURRENT形式的UPDATE和DELETE语句修改或删除之。即UPDATE语句和DELETE语句中要用子句:

WHERE CURRENT OF <游标名>

来表示修改或删除的是最近一次取出的记录,即游标指针指向的记录。

[例8.1]中的UPDATE就是用CURRENT形式的。

注意:当游标定义中的SELECT语句带有UNION或ORDER BY子句,或者该SELECT语句相当于定义了一个不可更新的视图时,不能使用CURRENT形式的UPDATE语句和DELETE语句。

8.1.5 动态SQL

前面所讲的嵌入式SQL语句中使用的主变量、查询目标列、条件等都是固定的,属于静态SQL语句。静态嵌入式SQL语句能够满足一般要求,但某些应用可能要到执行时才能够确定要提交的SQL语句、查询的条件,此时就要使用动态SQL语句来解决这类问题。动态SQL方法允许在程序运行过程中临时“组装”SQL语句。动态SQL支持动态组装SQL语句和动态参数两种形式,给开发者提供设计任意SQL语句的能力。

1.使用SQL语句主变量

程序主变量包含的内容是SQL语句的内容,而不是原来保存数据的输入或输出变量,这样的变量称为SQL语句主变量。SQL语句主变量在程序执行期间可以设定不同的SQL语句,然后立即执行。

[例8.6] 创建基本表 TEST。

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语句*/

2.动态参数

动态参数是SQL语句中的可变元素,使用参数符号(?)表示该位置的数据在运行时设定。和前面使用的主变量不同,动态参数的输入不是编译时完成绑定,而是通过PREPARE语句准备主变量和执行语句EXECUTE绑定数据或主变量来完成。使用动态参数的步骤如下:

(1)声明SQL语句主变量

SQL语句主变量的值包含动态参数(?)。

(2)准备SQL语句(PREPARE)

PREPARE将分析含主变量的SQL语句内容,建立语句中包含的动态参数的内部描述

符,并用<语句名>标识它们的整体。

EXEC SQL PREPARE <语句名> FROM ;

3.执行准备好的语句(EXECUTE)

EXECUTE将SQL语句中分析出的动态参数和主变量或数据常量绑定,作为语句的输入或输出变量。

EXEC SQL EXECUTE <语句名> [INTO <主变量表>][USING <主变量或常量>];

[例8.7]向TEST中插入元组。

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; /*执行语句, 设定INSERT语句插入值100*/

EXEC SQL EXECUTE mystmt USING 200; /*执行语句, 设定INSERT语句插入值200*/

8.2 过程化SQL

SQL 99标准支持过程和函数的概念,SQL可以使用程序设计语言来定义过程和函数,也可以用关系数据库管理系统自己的过程语言来定义。Oracle的PL/SQL、Microsoft SQLServer的Transact-SQL、IBM DB2的SQL PL、Kingbase的PL/SQL都是过程化的SQL编程语言。本节介绍过程化SQL (Procedural Language/SQL, PL/SQL)。

8.2.1过程化 SQL的块结构

基本的SQL是高度非过程化的语言。嵌入式SQL将SQL语句嵌入程序设计语言,借助高级语言的控制功能实现过程化。过程化SQL是对SQL的扩展,使其增加了过程化语句功能。

过程化SQL程序的基本结构是块。所有的过程化SQL程序都是由块组成的。这些块之间可以互相嵌套,每个块完成一个逻辑操作。图8.2是过程化SQL块的基本结构。

8.2.2变量和常量的定义

1.变量定义

变量名 数据类型 [[NOT NULL]:=初值表达式]或

变量名 数据类型 [[NOT NULL]初值表达式]

《数据库系统概论》学习笔记_第20张图片

2.常量的定义

常量名 数据类型 CONSTANT:=常量表达式

常量必须要给一个值,并且该值在存在期间或常量的作用域内不能改变。如果视图修改它,过程化SQL将返回一个异常。

3.赋值语句

变量名:=表达式

8.2.3 流程控制

过程化SQL提供了流程控制语句,主要有条件控制语句和循环控制语旬。这些语句的语法、语义和一般的高级语言(如C语言)类似,这里只做概要的介绍。读者使用时要参考具体产品手册的语法规则。

1.条件控制语句

一般有三种形式的IF语句: IF-THEN 语句、IF-THEN-ELSE 语句和嵌套的IF语句。

(1) IF语句

IF condition THEN

Sequence_ of_statements; /*条件为真时语句序列才被执行*/

END IF;

/*条件为假或NULL时什么也不做,控制转移至下一个语句*/

(2) IF-THEN语句

IF condition THEN

Sequence_ of_statements1;

/*条件为真时执行语句序列1*/

ELSE

Sequence_ of_statements2;

/*条件为假或NULL时执行语句序列2*/

END IF;

(3)嵌套的IF语句

在THEN和ELSE子句中还可以再包含IF语句,即IF语句可以嵌套。

2.循环控制语句

过程化SQL有三种循环结构: LOOP, WHILE-LOOP和FOR-LOOP。

(1)最简单的循环语句LOOP

LOOP

Sequence_ of_statements;

/*循环体,一组过程化 SQL语句*/

END LOOP;

多数数据库服务器的过程化SQL都提供EXIT、BREAK或LEAVE等循环结束语句,以保证LOOP语句块能够在适当的条件下提前结束。

(2) WHILE-LOOP循环语句

WHILE condition LOOP

Sequence of statements; /* 条件为真时执行循环体内的语句序列*/

END LOOP;

每次执行循环体语句之前首先要对条件进行求值,如果条件为真则执行循环体内的语句序列,如果条件为假则跳过循环并把控制传递给下一个语句。

(3) FOR-LOOP循环语句

FOR count IN [REVERSE] bound1 .. bound2 LOOP

Sequence of statements;

END LOOP;

FOR循环的基本执行过程是:将count设置为循环的下界bound1,检查它是否小于上界bound2。当指定REVERSE时则将count设置为循环的上界bound2,检查count是否大于下界bound1。如果越界则执行跳出循环,否则执行循环体,然后按照步长(+1或-1)更新count的值,重新判断条件。

3.错误处理

如果过程化SQL在执行时出现异常,则应该让程序在产生异常的语句处停下来,根据异常的类型去执行异常处理语句。

SQL标准对数据库服务器提供什么样的异常处理做出了建议,要求过程化SQL管理器提供完善的异常处理机制。相对于嵌入式SQL简单地提供执行状态信息SQLCODE,这里的异常处理就复杂多了。读者要根据具体系统的支持情况来进行错误处理。

8.3 存储过程和函数

过程化SQL块主要有两种类型,即命名块和匿名块。前面介绍的是匿名块。匿名块每次执行时都要进行编译,它不能被存储到数据库中,也不能在其他过程化SQL块中调用。过程和函数是命名块,它们被编译后保存在数据库中,称为持久性存储模块(Persistent Stored Module, PSM), 可以被反复调用,运行速度较快。SQL 2003标准支持SQL/PSM。

8.3.1 存储过程

存储过程是由过程化SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,因此称它为存储过程,使用时只要调用即可。

1.存储过程的优点

使用存储过程具有以下优点:

(1)由于存储过程不像解释执行的SQL语句那样在提出操作请求时才进行语法分析和优化工作,因而运行效率高,它提供了在服务器端快速执行SQL语句的有效途径。

(2)存储过程降低了客户机和服务器之间的通信量。客户机上的应用程序只要通过网络向服务器发出调用存储过程的名字和参数,就可以让关系数据库管理系统执行其中的多条SQL语句并进行数据处理。只有最终的处理结果才返回客户端。

(3)方便实施企业规则。可以把企业规则的运算程序写成存储过程放入数据库服务器中,由关系数据库管理系统管理,既有利于集中控制,又能够方便地进行维护。当企业规则发生变化时只要修改存储过程即可,无须修改其他应用程序。

2.存储过程的用户接口

用户通过下面的SQL语句创建、执行、修改和删除存储过程。

(1)创建存储过程

CREATE OR REPLACE PROCEDURE过程名([参数1,参数..... /*存储过程首部*/

AS <过程化SQL块>;

/*存储过程体,描述该存储过程的操作*/

存储过程包括过程首部和过程体。在过程首部,“过程名"是数据库服务器合法的对象标识;参数列表[参数1,参数2,..]用名字来标识调用时给出的参数值,必须指定值的数据类型。可以定义输入参数、输出参数或输入/输出参数,默认为输入参数,也可以无参数。

过程体是一个<过程化SQL块>,包括声明部分和可执行语句部分。<过程化SQL块>的基本结构已经在8.2节中讲解了。

以下部分插播三级数据库技术教程:

第10章 数据库运行维护与优化

完成数据库应用系统的设计并实施后,数据库系统则进入运行维护阶段。这个阶段的主要任务是保证数据库系统安全、可靠且高效率地运行。

通常,随着系统的使用,会产生数据库性能问题,本章结合数据库系统的日常运行维护工作介绍一些常用的数据库优化方法。

10.1 数据库运行维护基本工作

在数据库设计并试运行后,如果试运行结果符合设计目标,就意味着数据库可以真正投人运行了,同时也标志着开发任务的基本结束和维护工作的开始。在数据库系统运行过程中必须不断地对其进行监控、评价、调整与修改,以保证数据库系统正常和高效地运行。

一般来说,维护工作主要包括:数据库的转储和恢复;数据库的安全性和完整性控制;数据库性能的监控分析和改进;数据库的重组和重构。

①数据库的转储与恢复

数据库的转储和恢复是系统正式运行后最重要的维护工作之一。作为数据库管理员,应该针对各种数据制订合理的转储计划,定期对数据库和日志文件进行备份,保证数据库一旦出现故障,也有能力恢复到正常状态。为了保证转储数据能够正常进行恢复,通常情况下,数据库管理员需要定期对转储的数据进行恢复测试工作。恢复测试工作一般情况下是在与正式运行环境类似的环境中,利用转储数据进行数据库数据的恢复,恢复完成后对数据库中数据进行检查,确认数据的完整性、可靠性和一致性。

②数据库的安全性、完整性控制

保证数据库的安全性和完整性是数据库管理员的另一项重要任务。数据库管理员可以通过行政手段制订规范,同时通过权限管理、口令、跟踪及审计等来保证数据库的安全性。另外,数据库管理员应该维护多个数据副本,可能的话将这些副本存放在不同的安全地点。并采取有效措施预防和及时清除病毒,避免其对数据库的威胁。

同时,在数据库运行过程中,由于应用环境的变化,安全性要求也会发生变化,例如有的数据原来是机密的,经过一段时间后变成了公开的数据,而新加入的数据可能仍然处于机密状态。 系统中的用户安全要求也会发生变化。这些变化都需要数据库管理员根据实际情况修改原有的安全控制策略。

同样,数据库的完整性约束条件也会发生变化,也需要数据库管理员不断修正,以满足用户的需求。

③检测并改善数据库的性能

数据库管理员应该经常检测数据库系统的运行.观察数据库的动态变化情况,以便在数据库出现故障时能够及时恢复或者采取其他有效措施保护数据库。目前, 大部分数据库管理系统都提供了检测系统性能参数的工具,数据库管理员可以利用这些工具方便地得到系统运行过程中的一系列性能参数值。数据库管理员应仔细分析这些数据,判断当前系统运行状况是否满足应用和用户的需求,应当进行哪些改进。例如调整系统的物理参数,或对数据库进行重组或重构等。同时,由于性能优化本身是无止境的,在进行系统性能调整过程中,数据库管理员要平衡性能调整的投人和产出比,以满足应用系统需求为基准进行性能优化。

④数据库的重组和重构

数据库管理员应该定期对数据库进行重组,即按照系统设计要求对数据库存储空间进行全面调整,如调整磁盘分区方法和存储空间,重新安排数据的存储,整理回收碎块等,以提高数据库性能。这是因为在数据库长期运行过程中,由于对数据表内容的反复增、删、改使得存储空间的分配过于零散,导致存取效率下降,所以定期重组数据库是十分必要的。

数据库的重新组织并不修改数据库原有设计的逻辑结构和物理结构,而数据库的重构则不同,它是指部分修改数据库的模式和内模式。由于数据库应用环境的不断变化,增加了新的应用或新的实体,取消了某些应用,有的实体与实体间的联系也发生了变化等,使得原有的数据库设计不能满足新的需求,此时需要调整数据库的模式和内模式。例如,当业务应用需求出现小范围变化时,可能会要求对数据库的逻辑结构做必要的改变,要求在原来的数据库设计的基础上做适当的扩充或修改(如为一个表增加一个字段,改变某列数据类型等)。当然数据库的重构也是有限的,只能做部分修改,如果应用需求变动太大,重构也不能达到系统要求,则应该考虑重新设计数据库及相应的应用程序。

10.2 运行状态监控与分析

所谓数据库的监控分析,是指管理员借助相应工具在数据库运行过程中监测数据库系统的运行情况,掌握系统当前或以往的负荷、配置、应用和其他相关信息,并对监测数据进行分析,分析数据库的性能参数和环境信息,评估系统的整体运行状态,为系统的安全运行和性能调优提供依据,并提出相应的改善措施,帮助管理人员尽早消除数据库的性能隐患。

根据监控分析实现方法的不同,监控分析机制分为两种,一种是由数据库系统建立的自动监控机制,另一种是由管理员手动实施的监控机制。

①自动监控机制

该机制由DBMS自动监测数据库的运行情况,并在数据库出现问题时自动采取有效措施,防止出现的问题对数据库运行产生不良影响。

②手动监控机制

数据库管理员要随时观察数据库的动态变化,并在数据库出现错误、故障或产生不适应的情况(如数据库死锁、对数据库的误操作等)时能够随时采取有效措施保护数据库。

根据监控对象的不同,监控分析又可以分为对数据库构架体系的监控和对数据库性能的监控。

③对数据库构架体系的监控

主要监控内容:空间基本信息、空间使用率与剩余空间大小、空间是否具有自动扩展的能力,哪些表的扩展将引起空间的扩展,以及段的占用空间与区间数等。

④对数据库性能的监控

主要监控内容:数据缓冲区的命中率、库缓冲、用户锁、锁与等待、回滚段、临时段使用情况、索引的使用情况、等待事件和共享池等。

10.3 数据库存储空间管理

在数据库系统的运行过程中,对数据库空间使用情况,特别是空间的增长情况进行监控,并采取相应措施对数据库使用空间进行管理是项非常重要的工作。

对数据库的使用空间进行管理是十分必要的,这是因为在数据库系统运行过程中,随着用户程序对数据库的操作,会带来数据量的变化,使数据库出现许多数据碎片。一般情况下,数据库所需空间是不断增长的,硬盘可用存储空间会逐步缩小。空间使用情况的变化会带来许多问题,例如,数据量增大和碎片会导致数据库系统服务性能降低,系统空间的溢出有时会带来灾难性的停机故障,不少国内外知名大企业的在线服务系统都曾出现过因空间管理不到位而导致的灾难性停机事故,导致大面积服务停止,给企业和社会带来巨大的损失。所以数据库空间的监控和有效管理对整个数据库系统的正常运行以及性能优化具有十分重要的作用。

数据库的存储结构一般分为逻辑存储结构和物理存储结构,其物理存储结构决定了数据库存储数据时数据文件所占用空间的大小及分布。

针对不同的数据库产品,其逻辑存储结构和物理存储结构的对应方式是不同的。例如在Oracle和DB2数据库中,在逻辑上一个数据库由一个或多个表空间组成,表空间由段组成,段由区(extents)组成,区由若干个数据块构成;在物理上数据库由数据文件重做日志文件、控制文件组成,任何一个表空间至少对应-个或者多个数据文件 ,如图 10.1所示。而在SQL Server数据库中,两者的对应方式则有所不同,一个逻辑上的数据库直接和一组物理上的数据文件对应,没有表空间的概念。所以,不同的数据库对空间的管理也是不样的。

尽管如此,无论是何种数据库产品,通常对空间的管理主要包括创建数据库空间,更改空间大小,删除空间,修改空间状态, 新建、移动、关联数据文件等。一旦数据库的存取性能降低、速度减慢,在整体存储量尚可满足数据文件存特需求的情况下,可通过观测一定的表或视图来了解当前空间的使用状况,进而作出可能的调整决定。

除此之外,在进行数据库设计时,需要根据数据库的数据保存期要求数据结构信息和数据预期增长速度等因索,对数据库所需使用的空间进行预测,这也是一项十分重要的工作。预测出数据库中初始阶段要存放的数据量,并计算出数据库近两年所需要的空间以后,在实施阶段就必须以这些空间量为参数,在软硬件环境中为数据库预留出足够的空间。

随着数据库系统的不断运行,数据库中所存放的数据会因企业业务的不断开展而不断增长,企业业务开展情况也会与设计时估计的情况有所不同。因此,对数据库空间实际增长情况进行监控是非常重要的。应重点监控数据增长较快的数据表,并统计这此表的实际数据增长率,及时制订数据备份与转储策略,在数据量超过数据库存储能力前,及时增加这些表的存储空间。如果现有硬件空间已快不足以支持数据量拓展的要求,应该考虑是否做硬件上的扩容或者将一些与目前应用不是很紧密的历史数据及时转移到其他廉价数据存储介质中,或者转移到其他数据体系如数据仓库体系中,为数据库腾出足够的空间存放未来的数据。

以本书商场经营管理系统应用为例,在商场业务系统使用之初,假设该系统是随开业同时启用的。此时,数据库中没有销售细节数据,仅有些初始数据,如商品目录、人员信息、供应商信息等,不需太多的存储空间。在数据库实施时,必须为一定时间期限内的数据预留足够的空间,以保证业务系统的正常运行。

《数据库系统概论》学习笔记_第21张图片

随着商场的运作,商场业务数据库系统的多个表中各种信息在不断增加和变动,但其中有些表的空间占有量基本没变或增幅较小,如人员信息表、供应商信息表等,可能一天增加几条记录甚至是数天才增加一条记录。但是其他的一些数据表如商品销售细节表、商品人库明细表数据增长速度很快。如销售明细表中存放了商场每天销售的所有商品的详细记录,每天会增加上万条甚至数十万条记录。对于前一种数据增长速度很慢的数据表,无须过分关注其空间占用量的增长;但是对于后一种数据增长速度很快的表,管理员应格外关注其空间使用情况,因为一且没有及时预留出足够的空间,就很可能会出现因为数据库空间不足而使系统停止运转,影响商场的正常运作。

为了防止空间异常情况的发生,数据库管理员应结合商场销售的历史记录,预测未来一段时间内每天会增长多少条记录,从而预测出目前数据库中的剩余空间能够继续使用多长时间,如果发现空间不足,可以考虑扩大存储容量。如若不能进行硬件扩展,应考虑制订合理的数据备份和转储策略,调整数据保存期,将远期的历史数据,如几年前的数据,转移到其他廉价存储介质中去,如光盘、磁带等,从而为新的业务数据腾出足够的存储空间。

10.4 数据库性能优化

数据库性能优化是数据库应用系统上线后最常见的运行维护任务之一。但是,数据库性能优化对数据库管理员的要求也比较高。调整一个数据库应用系统的性能要求熟悉系统环境、数据库管理系统、应用程序以及应用程序所使用的数据。甚至一个具有丰富经验的数据库管理员,在进行数据库优化过程中都可能遭受到很严峻的考验。同时,在进行数据库性能优化时,需要首先确定优化目标。由于优化本身是无止境的,如果在不明确优化目标的情况下不断进行优化,就可能导致投入过多的成本,造成优化项目的失败。

数据库性能优化一般可以从数据库运行环境、数据库参数调整、模式调整、数据库存储优化及查询优化几个方面考虑。

10.4.1 数据库运行环境与参数调整

数据库系统运行需要依赖服务器操作系统存储、网络等多种因素。当这些数据库环境出现瓶颈时就会导致数据库运行变慢,甚至是无法完成正常业务。一般来说,在数据库发现性能问题时,首先需要对数据库运行环境进行检查。

一般来说,可以从外部环境、调整内存分配、调整磁盘I/O、调整资源竞争等几个方面着手来改变数据库的参数,提高其性能。

1.外部调整

数据库并不是脱离于外部环境单独运行的。也就是说,数据库的性能和外部环境有很大的关系,如果外部环境出现瓶颈,再多的数据库调整都是没有帮助的。

这些外部的条件主要包括:

①CPU

当数据库操作对CPU性能的要求超过数据库服务器的CPU性能时,数据库性能就受到CPU的限制,使数据库操作变慢。所以,在任何机器中,CPU的数据处理能力往往是衡量计算机性能的一个标志。如果运行队列数目超过了CPU处理的数目,服务器性能就会受到CPU的限制而下降。解决方法是为服务器适当增加CPU的数量或者是终止需要许多资源的进程。

对于一台数据库服务器来说,如果其在业务空闲时使用率超过90%, 说明服务器缺乏CPU资源;如果工作高峰时CPU使用率仍然很低,则说明服务器CPU资源充足。据此,可以判断一个数据库系统CPU的使用情况。

②网络

大量的SQL数据在网络上传输会导致网速变慢。网卡、交换机、集线器等网络设备的性能对网络的影响很明显。所以,通过调整网络设备,也可以在一定程度上提高数据库系统的性能。

2.调整内存分配

通过调整相关参数控制数据库的内存分配,也可以在很大程度上改善数据库系统的性能。

3.调整磁盘I/O

数据库性能优劣的一个重要度量是响应时间,而I/O时间是响应时间的最大组成部分。因此,可以通过令I/O时间最小化,减少磁盘上的文件竞争带来的瓶颈等方法来改善数据库系统的性能。

4.调整竞争

资源是有限的,多个进程对相同的资源发出申请时,导致了竞争的产生。为了解决这个问题,可以采用以下几种方法:

①修改参数以控制连接到数据库的最大进程数。

②减少调度进程的竞争。

③减少多线程服务进程竞争。

④减少重做日志缓冲区竞争。

⑤减少回滚段竞争。

10.4.2 模式调整与优化

在数据库设计阶段,主要强调的是高效率利用存储空间,减少数据的冗余,减少数据的不一致,这个过程也就是规范化的过程。大多数情况下,数据库系统需要考虑的第二个目标是高效率地进行数据处理。通常情况下,一个关系中出现的所有属性并不被一起使用,而来自不同关系的数据则可能需要起使用来进行查询或生成报表。 因此,虽然规范化关系解决了数据维护的异常,并使冗余最小化,然而,可能会出现数据处理性能下降的问题。

完全规范化的数据库通常会产生很多表。对于一个频繁使用的查询,如果它要求操作多个

相关表中的数据,则每次为生成需要的查询结果而在连接多个表中相关行时,数据库管理系统就

会消耗更多的计算机资源。因为连接操作非常耗时,所以完全规范化数据库和部分规范化数据

库之间处理性能会有很大差别。

反规范化是将规范化的关系转换为非规范化的关系的过程。常用的反规范化方法有增加派生冗余列、增加冗余列、重新组表分割表和新增汇总表等方法。

1.增加派生性冗余列

派生性冗余列是指表中增加的列由表中的些数据项经过计算生成。它的作用是在查询时减少连接操作,避免使用聚合函数。例如:销售单据明细表(销售单据编号,商品编号,单价,数量,总价,折扣率,折扣总价)中,由于“总价”字段值可以由“单价×数量"得到,说明“总价”是派生性冗余列。按照规范化理论在设计此表时是不应要“总价”字段的。若不要该字段,那么每次使用到总价时,都要先执行代码计算后才能使用,如果商品的数量较多,而且要频繁使用到总价数据时,计算总价代码的执行次数也随着增加,这显然会影响到数据库的运行效率;若增加“总价”这个派生性冗余字段,虽然破坏了规范化原则,但只需执行一次计算总价代码就可以把商品金额存到数据库中,以后不管什么时候使用总价字段,只需提取其值即可,不必再执行计算代码。不难看出,增加“总价”字段后,可以提高查询统计的处理速度,从而达到以空间换时间的目的。在此例子中“折扣总价”也属于派生性冗余列。

2.添加冗余列

增加冗余列是指在多个表中增加具有相同语义的列,它常用来在查询时避免连接操作。值得一提的是,主码与外码在多表中的重复出现不属于冗余列,这里所指的冗余列是非键字段的在多表中的重复出现。 例如,假设教学管理数据库中所含的数据项如下:学号、姓名、生日、系别、系主任姓名 、课程号、成绩;若按照规范化设计则该数据库涉及的信息应分解成三个关系模式:

学生(学号、姓名、出生日期、系别)

系(系别、系主任姓名)

选课(学号、课程号、成绩)

很显然,这个数据库设计是规范的、合理的。假如在这个数据库中我们想通过学生的学号来查询其所在系的系主任姓名,那么这个操作必然要进行“学生"和“系”两个表的连接操作,若在数据库使用过程中,这类查询操作需要频繁提交,由于表的连接操作是比较费时的,因此按规范化要求设计出来的这样一个数据库却发挥不出最好的性能。

如果在“学生”关系中增加“系主任姓名”这个冗余列,这显然破坏了规范化规则,然而在进行行以上查询操作时不用进行表的连接操作,从而提高了查询速度,使系统得到优化。值得一提的是,增加冗余列可以在查询时避免连接操作,但它需要更多的磁盘空间,同时也增加了维护表的工作量。因此不是任何情况下使用增加冗余列都能解决问题的,使用这种方法的前提条件是要保证冗余列及其对应列数据的一致性。

3.重新组表

当用户经常查看的某些数据是由多个表连接之后才能得到,就可以考虑先把这些数据重新组成一个表,这样在查询时会减少连接从而提高性能。例如,在以上的数据库例子中用户经常需要同时查着姓名、系别、课程号、成绩,则可把“学生”表和”选课”表合并成一个表P(姓名、系别、课程号、成绩),只需对表P进行查询。这样可提高性能,但需要更多的磁盘空间,同时,要考虑每当相关表中的数据变化时,刷新表P的代价。

4.分割表

在一些数据库中有些表的设计已经很合理,但是由于表中的数据过于庞大,或表中的数据具有使用独立性,有时为了提高性能,对表进行分割,这虽然破坏了数据表的整体性,但却使系统得到优化。表分割有两种方式:水平分割和垂直分割。

水平分割是根据数据行的使用特点进行分割,分割之后所得的所有表的结构都相同,而存储的数据不同。当表中分别记录各个地区的数据或不同时期的数据的情况下可对表进行水平分割。例如我国的身份证号码若放在一个表中,由于我国人口众多,因此数据量大,进行身份证查询时效率低。这时可以按省份对它进行水平分割,把不同区域的身份证号分别存储在不同的表中,查询时只需根据省份代码检索相应的表,这显然能提高查询速度。水平分割会给应用增加复杂度,特别在查询所有数据时需要Union(并)操作。在许多数据库应用中,这种复杂性会超过它带来的优点,因此,只有当表中的数据具有很好的使用独立性,即大部分情况是局部使用,只有很少情况才全局查询时适合使用此方法。

垂直分割是根据数据列的特点进行分割,分割之后所得的所有表中除了都含有主码列外其余列都不相同。一般在一个表中某些列常用,而另外此列不常用的情况下可以采用垂直分割,分割时把操作时常用与不常用的列分别放人不同的表中,这就使得数据行变小,一个数据页就能存放更多的数据,在查询时就会减少1I/0次数,而且大多数据操作只在少数或者一个表中进行,从而提高系统性能,但其缺点是查询所有数据时需要Join(连接)操作。

5.新增汇总表

在很多情况下,数据库出现性能问题是因为大量执行报表等汇总操作造成的。因为汇总过程可能需要同时对大批量数据进行实时访问,同时对数据进行加和取平均等操作。这些操作占用数据库服务器CPU大、持续时间长。为了降低这些操作的时间,可以根据统计操作的使用情况,将频繁使用的统计操作的中间结果或最终结果存储在汇总表中,当用户发出汇总需求时,即可直按从汇总表中获取数据,降低了数据访问量以及汇总操作的CPU计算量。例如在“商场经营管理系统”中,经常要对销售额进行统计,为了方便统计,可以将每天的销售额统计后放人日销售额统计表,在进行统计时,直接从日销售额统计表中读取数据,提高数据统计速度。

数据库的反规范化是为了减少表间的连接,提高查询性能,但并非所有经反规范的数据库都是高效的,这与实际的应用有关,只有满足一定条件的数据库采用反规范化方法才能提高性能。特别强调的是,无论使用何种反规范化技术,都可能破坏数据的完整性,因此,反规范化技术需要维护数据的完整.所以采用反规范化技术时,一定要权衡利弊,仔细分析应用的数据存取需求和实际的性能特点,从实际出发,选用适合当前应用的反规范化技术,只有这样才能达到提高性能、优化系统的目的。

10.4.3 存储优化

1.物化视图

物化视图是包括一个查询结果的数据库对象(可由系统定期刷新其中的数据),物化视图不是在使用时才读取,而是预先计算并保存表连接或聚集等耗时较多的操作结果,这样在查询时大大提高了读取速度,特别适用于多个数据量较大的表进行连接操作及分布式数据库中需要进行分布在多站点的表进行连接操作时使用。

物化视图还可以进行远程数据的本地复制,此时物化视图的存储也可以称为快照。主要用于实施数据库间的同步。

物化视图对于数据库客户端的使用者来说如同一个实际的表,具有和表相同的一般select操作,而其实际上是一个视图,一个定期刷新数据的视图。物化视图的刷新可采用自动刷新和人工刷新方式,具体刷新方式和刷新时间在定义物化视图的时候可以定义。使用物化视图可以实现视图的所有功能,因物化视图不是在使用时才读取,而大大提高了读取速度,特别适用抽取大数据量表中某些信息以及分布式环境中跨节点进行多表数据连接的场合。

2.聚集

聚集(Cluster)是物理存储表中数据的可选择的方法。一个聚集是一组表,可将经常一起使用的具有同一公共列值的多个表中的数据行存储在一起,由它们的公共列构成聚集码。如果经常被同时访问,就可以创建一个聚集,通过聚集码存储或查询这些表中的数据,从而最小化必须执行的I/O次数,改善系统性能。

多表中相关的列称为聚集码(Cluster Key),在将记录插人聚集的表中之前,必须要为聚集对象建立一个聚集索引(Cluster Index),且按聚集码进行索引;对于聚集中的多个表,聚集值只存储一次。对于经常频繁一起查询的表使用聚集比较方便。在聚集中,来自不同表的行存储在同一个数据块中。因此同将表分开存储相比,连接这些表的查询就可能执行更少的I/O。不过,与对非聚集表的相同操作比较,聚集表的插入、更新和删除性能要差很多,因此要根据具体情况权衡利弊。

10.4.4 查询优化

在数据库运行初期,数据库对SQL语句各种写法的性能优劣还不敏感,但是随着数据库的正式使用,数据库中数据的不断增加,劣质SQL语句和好的SQL语句之间的速度差就逐渐显示出来了。

以商场应用为例,业务系统一旦运行,商场的业务子系统就会在数据库服务器上产生各种增删改的事物或数据查询服务请求,随着系统不断运行,系统中的数据会不断增长,就很有可能会出现系统效率下降的情况。效率低下的SQL语句常常是系统效率不佳的主要原因。

下面介绍集中优化查询的常用方法。

1.合理使用索引

索引是数据库中重要的数据结构,建立索引的目的就是为了提高查询效率。查询的性能在很大程度上取决于存在什么样的索引来加快选择和连接的处理。同时,从另一方面看,在插入、删除成更新操作中,索引的存在又增加了系统的开销。因此,要在加快查询与事务处理效率方面获得的好处与增加开销之间进行权衡。

索引的物理设计决策涉及以下几类问题:

①是否为一个属性建立索引。该属性必须是一个码,或者必须存在某个查询,其选择条件(等值或范围)或连接条件中使用了该属性。之所以会建立多个索引,其因素之一是有些查询只需扫描索引即可处理,而无须检索任何数据。

②在哪些属性上建立索引。可以在一个或多个属性上构建索引。如果一个关系的多个属性共同出现在若干个查询中,则一般会使用多属性索引。而多属性索引中的属性顺序可以考虑按照其区分度进行排列。

③是否建立聚簇索引。一个表中最多只能有一个主索引或聚簇索引,因为该表必须按照这个属性物理排序。在大多数关系数据库中,都用关键词CLUSTER来指定聚簇索引(如果是码属性便创建主索引,如果不是码属性则创建聚簇索引)。如果一个表中需要多个索引,那么将哪个索引作为聚簇索引则取决于是否需要按照该属性排序。聚簇索引最适合用于范围查询。如果有多个属性需要范围查询,那么选择哪个索引作为聚簇索引则取决于是否要在该属性上对数据进行排序。如果一次查询只进行一次索引排序(没有数据记录存取过程),则相应的索引不应该被聚簇,因为聚簇的最大优点体现在数据记录存取过程中。当由复合键检索的范围用于报表创建时,聚簇索引就可能建立为多属性索引。

④使用散列索引还是树索引。通常,关系数据库管理系统中使用B+树作为索引,某些系统也提供散列索引。B+树索引支持作为搜索码的属性上的等值查询和范围查询。散列索引适用于等值查询,尤其是在连接操作中查找匹配记录时。

索引的使用要恰到好处,其使用原则一般如下:

①经常在查询中作为条件被使用的列,应为其建立索引。

②频繁进行排序或分组(即进行group by或order by操作)的列,应为其建立索引。

③一个列的值域很大时,应为其建立索引。

④如果待排序的列有多个,应在这些列上建立复合索引。

⑤可以使用系统工具来检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引也可以提高查询速度。

在索引建立完成后,数据库系统运行期间可能还需要对索引进行调整与修改,索引调整与修改主要基于以下一些原因:

●由于缺少索引,某些查询语句执行时间过长。

●某些索引自始至终没有使用,而索引占用了较多的磁盘空间。

●某些索引建立在被频繁改变的属性上,导致系统的开销过大。

大部分关系数据库管理系统都提供了相应的命令或跟踪工具,借助这些工具,数据库管理员可以从系统获得关于查询执行过程的信息,包括以何种顺序执行何种操作、使用何种辅助存取结构(例如索引)等。通过分析这些执行计划可以得到上述问题的原因。基于调优分析,可能会删除某些索引,也可能要增加新的索引。

调优的目的是动态地评估需求。这些需求可能随时间变化,例如在每月或每周的不同时间有所变化,并对索引进行重组以获得最好的整体性能。虽然在删除或新建索引的过程中会增加系统开销,但与性能的改进相比,这些开销是值得的。在删除或创建索引过程中,通常会延迟表的更新,必须考虑到由此导致的服务损失。除了删除或创建索引,以及非聚族索引和聚簇索引的相互转换之外,通过重建索引也可以改进系统的性能。大部分关系数据库管理系统使用B+树作为索引,如果在索引码上执行大量删除操作,索引页可能会出现空间的浪费,而这些被浪费的空间可能需要在重建索引后才可以被重用。同样,过多的插入操作也会导致聚簇索引的益出,这也将影响到性能。而重建聚簇索引相当于重组按此码排序的整个表。

索引的可用选项以及它们的定义、创建和重组方式因数据库管理系统不同而有所不同。以稀疏索引和稠密索引为例,稀疏索引对于数据文件的每个页面(数据块)有一个索引指针;而稠密索引对于每个记录都有索引指针。不同的数据库管理系统对相关指针的处理方式也有所不同,在数据库管理员使用这些索引过程中,需要考虑这些不同和限制。

2.避免或简化排序

通常,在运行Order by和Group by的SQL语句时,会涉及排序的操作,应当简化或避免对大型表进行重复的排序,因为磁盘排序的开销是很大的。与内存排序相比较,磁盘排序操作很慢,从而会花费很长时间,降低数据库性能,而且磁盘排序会消耗临时表空间中的资源。

当能够利用索引自动以适当的次序产生输出时,优化器就可以避免不必要的排序步骤。以下是一些影响因素:

①由于现有索引的不足,导致排序时索引中不包括一个或几个待排序的列。

②group by或order by子句中列的次序与索引的次序不一样。

③排序的列来自不同的表。

为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可能影响表的规范化,但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图简化它,如缩小排序列的范围等。

3.消除对大型表数据的顺序存取

在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。避免这种情况的主要方法就是对连接的列进行索引。还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。

4.避免复杂的正则表达式

在使用正则表达式进行条件查询时可能会消耗较多的CPU资源进行字符串匹配工作,因此应尽量避免。

5.使用临时表加速查询

把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。临时表中的行比主表中的行要少,而且顺序就是所要求的顺序,减少了磁盘的I/O操作,所以查询工作量可以得到大幅减少。

6.用排序来取代非顾序磁盘存取

非顺序磁盘存取是最慢的操作。但是在写SQL语句时往往忽略了这一点,使得在写应用程序时很容易写出要求存取大量非顺序页的查询,导致效率降低。有些时候,可以使用以数据库排序功能为基础的SQL来替代非顺序的存取,以改进查询效率。

7.不充分的连接条件

左(右)连接消耗的资源非常之多,因为它们包含与NULL(不存在)数据匹配的数据,其代价可能非常高。左(右)连接比内连接消耗资源更多,所以应尽可能不使用左(右)外连接的查询。

8.存储过程

平时每次向数据库发送的SQL脚本,都需要先编译后执行。这样当使用相同的语句时效率就会很低,而存储过程则不需要编译就能直接执行,因此速度可以更快。所以,对于频繁使用的SQL语句建议使用存储过程。另外,要注意在存储过程中尽量使用SQL自带的返回参数,而非自定义的返回参数,减少不必要的参数,避免数据冗余。

9.不要随意使用游标

游标会占用较多的系统资源尤其是在大规模并发的情况下,很容易使得系统因资源耗尽而崩溃。所以,不要随意使用游标,而且游标使用完后应及时关闭和销毁,以释放资源。

10.事务处理

为了同时操作多个表而保证数据库的一致性,往往会用到事务。但是一旦将多个处理放入事务当中,系统的处理速度会有所降低,所以应当在保证数据库一致性的前提下 ,将频繁操作的多个可分割的处理过程放入到多个存储过程当中,这样会大大提高系统的响应速度。

10.4.5 SQL Server性能工具

Microsoft SQL Server提供了一套综合的工具,用于监视SQL Server中的事件和优化物理数据库的设计。SQL Server中最常用的两个性能优化工具是SQL Server Profiler和数据库引擎优化顾问。

1. SQL Server Profiler

SQL Server Profiler 是用来监视SQL Server事件的工具,其监视事件的结果可以存储到一个跟踪文件中。通过分析该跟踪文件,可以得知数据库运行中的性能瓶颈,也可以用来诊断数据库在运行当中所遇到的某些问题。

SQL Server Profiler 可以监视几乎所有在SQL Server中可能发生的事件,因此SQL Server Profiler是个多用途的性能监控工具,除监视系统性能状态外,还可以监视存储过程、T-SQL语句的运行状态,以便程序除错、寻找SQL Server问题所在和监视用户操作等。

2.数据库引擎优化顾问

数据库引擎优化顾问可以在不精通数据库结构的情况下,通过对数据库的工作负荷测试,由数据库引擎优化顾问给出优化建议,然后再通过管理员进行相应的修改,使数据库达到一个比较优化的状态。

数据库引擎优化顾问通过分析一个或多个数据库的工作负荷和物理架构,然后提出优化建议。所谓的工作负荷也就是一组在数据库中执行的T-SQL语句,数据库引擎优化顾向分析这些T-SQL语句执行效率来提出优化建议,因此在数据库引擎优化顾问优化数据库时,会要求输人跟踪文件、跟踪表或者T -SQL脚本。

在数据库引擎优化顾问对工作负荷进行分析后,数据库引擎优化顾问会建议添加、修改或删数据库中的某些对象,如索引、视图等。

发使用数据库引擎优化顾问前,可以先运行SQL Server Profiler跟踪一些事件,然后将跟踪文件结果存储为文件供其使用。在产生跟踪文件时,应尽可能多地跟踪可能产生数据库运行瓶颈的事件,在运行跟踪时也应该尽可能多地运行存储过程和T-SQL语句。负荷文件越大、越详细,对数据库引擎优化顾问的分析越起作用。

(第10章完)

下面进入《数据库系统概论》的最后一章:

第16章 数据仓库与联机分析处理技术

第15章已经提到,计算机系统中存在着两类不同的数据处理工作:操作型处理和分析型处理,也称作联机事务处理(OLTP)和联机分析处理(OLAP)。

操作型处理也叫事务处理,是指对数据库联机的日常操作,通常是对一个或一组记录的查询和修改,如火车售票系统、银行通存通兑系统、税务征收管理系统等。这些系统要求快速响应用户请求,对数据的安全性、完整性以及事务吞吐量要求很高。

分析型处理是指对数据的查询和分析操作,通常是对海量的历史数据查询和分析,如金融风险预测预警系统、证券股市违规分析系统等。这些系统要访问的数据量非常大,查询和分析的操作十分复杂。

OLTP和OLAP两者之间的差异使得传统的数据库技术不能同时满足两类数据的处理要求,因此,20世纪80年代数据仓库(Data Warehouse, DW)技术就应运而生了。数据仓库的建立将操作型处理和分析型处理区分开来。传统的数据库技术为操作型处理服务,数据仓库为分析型处理服务。二者各司其职,泾渭分明。越来越多的企业认识到数据仓库能够带来效益,逐步在原有数据库基础之上建立起了自己的数据仓库系统。

随着大数据时代的来临,数据仓库对于企业决策的支持作用越来越大。由此,数据仓库也成为各大厂商看重并着力发展的业务领域。IBM、Oracle、Teradata 等厂商纷纷采用各种软硬件技术(如MPP并行处理、列存储等),将其产品扩展到PB级数据量。另外,新兴的互联网企业也在尝试利用一些新技术(如MapReduce)开发能支持大规模非结构化数据处理的数据仓库解决方案,如Facebook在Hadoop基础上开发出Hive系统,用来分析点击流和日志文件。

16.1 数据仓库技术

数据仓库和数据库只有一字之差,似乎是一样的概念,但实际则不然。数据仓库是为了构建新的分析处理环境而出现的一种数据存储和组织技术。由于分析处理和事务处理具有极不相同的性质,因而两者对数据也有着不同的要求,数据仓库概念的创始人W.H.Inmon在其《Building the Data Warehouse》一书中列出了操作型数据与分析型数据之间的区别,具体如表16.1所示。

《数据库系统概论》学习笔记_第22张图片

基于上述操作型数据和分析型数据之间的区别,可以给出数据仓库的定义:数据仓库是一个用以更好地支持企业(或组织)决策分析处理的、面向主题的、集成的、不可更新的、随时间不断变化的数据集合。数据仓库本质上和数据库一样,是长期储存在计算机内的、有组织、可共享的数据集合。

1.数据仓库的基本特征

数据仓库和数据库主要的区别是数据仓库中的数据具有以下4个基本特征。

(1)主题与面向主题

数据仓库中的数据是面向主题进行组织的。主题是一个抽象的概念,是在较高层次上将企业信息系统中的数据综合、归类并进行分析利用的抽象:在逻辑意义上,它对应企业中某一宏观分析领域所涉及的分析对象。例如对一家商场而言,概括分析领域的对象,应有的主题包括供应商、商品、顾客等。面向主题的数据组织方式是根据分析要求将数据组织成一个完备的分析领域,即主题域。

主题是一个在较高层次上对数据的抽象,这使得面向主题的数据组织可以独立于数据的处理逻辑,因而可以在这种数据环境上方便地开发新的分析型应用:同时这种独立性也是建设企业全局数据库所要求的,所以面向主题不仅适用于分析型数据环境的数据组织方式,同时也适用于建设企业全局数据库的组织。

(2)数据仓库是集成的

前面已经讲到,操作型数据与分析型数据之间差别甚大,数据仓库的数据是从原有的分散的数据库数据中抽取来的,因此数据在进入数据仓库之前必然要经过加工与集成,统一与综合。这一步实际是数据仓库建设中最关键、最复杂的一步。

首先,要统一原始数据中所有矛盾之处,如字段的同名异义、异名同义,单位不统一,字长不一致等;然后将原始数据结构作-一个从面向应用到面向主题的大转变;还要进行数据综合和计算。数据仓库中的数据综合工作可以在抽取数据时完成,也可以在进入数据仓库以后进行综合时完成。

(3)数据仓库是不可更新的

数据仓库主要供决策分析之用,所涉及的数据操作主要是数据查询,一般情况下并不进行修改操作。数据仓库存储的是相当长段时间内的历史数据,是不同时点数据库快照的集合,以及基于这些快照进行统计、综合和重组的导出数据,不是联机处理的数据。OLTP数据库中的数据经过抽取(Extracting)、清洗(Cleaning)、 转换(Transformation) 和装载(Loading)存放到数据仓库中(这一过程简记为ECTL)。一旦数据存放到数据仓库中,数据就不可再更新了。

(4)数据仓库是随时间变化的

数据仓库中的数据不可更新,是指数据仓库的用户进行分析处理时是不进行数据更新操作的,但并不是说在数据仓库的整个生存周期中数据集合是不变的。

数据仓库的数据是随时间的变化不断变化的,这一特征表现在以下三方面。第一,数据仓库随时间变化不断增加新的数据内容。第二,数据仓库随时间变化不断删去旧的数据内容。第三,数据仓库中包含大量的综合数据,这些综合数据中很多与时间有关,如数据按照某一时间段进行综合,或隔-定的时间片进行采样等,这些数据就会随着时间的变化不断地进行重新综合。因此,数据仓库中数据的标识码都包含时间项,以标明数据的历史时期。

2.数据仓库中的数据组织

数据仓库中的数据分为多个级别:早期细节级、当前细节级、轻度综合级和高度综合级。数据仓库的数据组织结构如图16.1所示。源数据经过抽取、清洗、转换、装载进入数据仓库。首先进入当前细节级,根据具体的分析处理需求再进行综合,进而成为轻度综合级和高度综合级。随着时间的推移,早期的数据将转入早期细节级。

《数据库系统概论》学习笔记_第23张图片

由于数据仓库的主要应用是分析处理,绝大部分查询都针对综合数据,因而多重级别的数据组织可以大大提高联机分析的效率。不同级别的数据可以存储在不同的存储设备上。例如,可以将综合级别高的数据存储于快速设备甚至放在内存中。这样,对于绝大多数查询分析,系统性能将大大提高;而综合级别低的数据则可存储在磁带磁盘阵列、光盘组或磁带上。

3.数据仓库系统的体系结构

数据仓库系统的体系结构如图16.2所示,由数据仓库的后台工具、数据仓库服务器、OLAP服务器和前台工具组成。

《数据库系统概论》学习笔记_第24张图片

数据仓库的后台工具包括数据抽取、清洗、转换、装载和维护(maintain) 工具,简记为ECTL工具或ETL工具。

数据仓库服务器相当于数据库系统中的数据库管理系统,它负责管理数据仓库中数据的存储管理和数据存取,并给OLAP服务器和前台工具提供存取接口(如SQL查询接口)。数据仓库服务器目前二般是关系数据库管理系统或扩展的关系数据库管理系统,即由传统数据库厂商对数据库管理系统加以扩展修改,使它能更好地支持数据仓库的功能。

OLAP服务器透明地为前台工具和用户提供多维数据视图。用户不必关心它的分析数据(即多维数据)到底存储在什么地方,是怎么存储的。

前台工具包括查询报表工具、多维分析工具、数据挖掘工具和分析结果可视化工具等。

16.2 联机分析处理技术

联机分析处理是以海量数据为基础的复杂分析技术。联机分析处理支持各级管理决策人员从不同的角度,快速灵活地对数据仓库中的数据进行复杂查询和多维分析处理,辅助各级领导进行正确决策,提高企业的竞争力。

1.多维数据模型

多维数据模型是数据分析时用户的数据视图,是面向分析的数据模型,用于给分析人员提供多种观察的视角和面向分析的操作。

多维数据模型的数据结构可以用一个多维数组来表示: (维1,维2,……,维n,度量值)。例如,某电器商品销售数据是按时间、地区、电器商品种类,加上度量“销售额”组成的一个三维数组(地区,时间,电器商品种类,销售额)。三维数组可以用一个立方体来直观地表示。一般地,多维数组用多维立方体CUBE来表示。多维立方体CUBE也称为超立方体。

2.多维分析操作

常用的联机分析处理多维分析操作有切片(slice)、 切块(dice)、 旋转(pivot)、 向上综合(roll-up)、 向下钻取(drill-down) 等。通过这些操作,使用户能从多角度和多侧面观察数据、剖析数据,从而深入地了解包含在数据中的信息与内涵。

3.联机分析处理的实现方式

联机分析处理服务器透明地为分析软件和用户提供多维数据视图,实现对多维数据的存储、索引、查询和优化等功能。联机分析处理服务器一般按照多维数据模型的不同实现方式,分为MOLAP结构、ROLAP结构、HOLAP结构等多种结构。

MOLAP结构直接以多维立方体CUBE来组织数据,以多维数组来存储数据,支持直接对多维数据的各种操作。人们也常常称这种按照多维立方体来组织和存储的数据结构为多维数据库(Multi-Dimension DataBase, MDDB)。

ROLAP结构用关系数据库管理系统或扩展的关系数据库管理系统来管理多维数据,用关系表来组织和存储多维数据。同时,它将多维立方体上的操作映射为标准的关系操作。

ROLAP将多维立方体结构划分为两类表,一类是事实表(fact table),另一类是维表。事实表用来描述和存储多维立方体的度量值及各个维的码值;维表用来描述维信息。ROLAP用关系数据库的二维表来表示事实表和维表,也就是说,ROLAP用“星形模式”和“雪片模式”来表示多维数据模型。

星形模式(star schema)通常由一个中心表(事实表)和一组维表组成。如图16.4 所示的星形模式的中心是销售事实表,其周围的维表有时间维表、顾客维表、销售员维表、制造商维表和产品维表。事实表一般很大,维表一般较小。

将星形模式中的维表按层次进一步细化, 就形成雪片模式。例如,对于图16.4的星形模式,顾客维表可以所在地区位置分类聚集;时间维表则可以有两类层次——日、月,日、星期;制造商维表可以按工厂及工厂所在地区分层等。如图16.5所示,在星形维表的角上又出现了分支,这样变形的星形模式被称为雪片模式(snow flake schema)。

HOLAP (Hybrid OLAP)则是MOLAP和ROLAP的混合结构。

联机分析处理软件提供的是多维分析和辅助决策功能,对于深层次的分析和发现数据中隐含的规律和知识,则需要数据挖掘(Data Mining, DM)技术和相应的数据挖掘软件来完成。

16.3 数据挖掘技术

1.数据挖掘的概念

数据挖掘是从大量数据中发现并提取隐藏在内的、人们事先不知道的但又可能有用的信息和知识的一种新技术。

数据挖掘的目的是帮助决策者寻找数据间潜在的关联,发现经营者忽略的要素,而这些要素对预测趋势、决策行为也许是十分有用的信息。

数据挖掘技术涉及数据库、人工智能、机器学习、统计分析等多种技术,它使决策支持系统(Decision Support System, DSS) 跨入了一个新阶段。

2.数据挖掘和传统分析方法的区别

传统的决策支持系统通常是在某个假设的前提下通过数据查询和分析来验证或否定这个假设。数据挖掘与传统的数据分析(如查询、报表、联机应用分析)的本质区别是数据挖掘是在没有明确假设的前提下去挖掘信息,发现知识。

数据挖掘技术是基于大量的来自实际应用的数据,进行自动分析、归纳推理,从中发掘出数据间潜在的模式或产生联想,建立新的业务模型以帮助决策者调整企业发展策略,进行正确决策。

数据挖掘所得到的信息应具有事先未知、有效和可实用三个特征。

事先未知的信息是指该信息是未曾预料到的,即数据挖掘是要发现那些不能靠直觉发现的信息或知识,甚至是违背直觉的信息或知识。挖掘出的信息越是出乎意料,就可能越有价值。例如,在商业应用中一个最典型的例子就是,一家连锁店通过数据挖掘发现了小孩尿布和啤酒之间的销售模式有着惊人的联系。

3.数据挖掘的数据源

数据挖掘的数据主要有两种来源,即数据可以是从数据仓库中来的,也可以是直接从数据库中而来。这些实际的应用数据往往是不完全的、有噪声的、模糊的、随机的,因此要根据不同的需求在挖掘之前进行预处理。

从数据仓库中直接得到数据挖掘的数据有许多好处。因为数据仓库的数据已经过了预处理,许多数据不一致的问题都较好地解决了,在数据挖掘时大大减少了清洗数据的工作量。

当然为了数据挖掘也不必非得建立一个数据仓库,数据仓库不是必需的。建立一个巨大的数据仓库,要把各个不同源的数据集成在一起,解决所有的数据冲突问题,然后把所有的数据导到一个数据仓库内,这是一项巨大的工程,可能要用几年的时间、花上百万的经费才能完成。如果只是为了数据挖掘,可以把一个或几个联机分机处理数据库导入一个只读的数据库中,然后在上面进行数据挖掘。

所有的数据还要再次进行选择,具体的选择方式与任务相关。挖掘的结果需要进行评价才能最终成为有用的信息,按照评价结果的不同,数据可能需要反馈到不同的阶段,重新进行分析计算。

4.数据挖掘的功能

数据挖掘的功能主要有以下几种:

(1)概念描述。即归纳总结出数据的某些特征。

(2)关联分析。若两个或多个变量的取值之间存在某种规律性,就称为关联。关联包括相关关联和因果关联。关联规则不仅是单维关联,也可能是多维之间的关联。

(3)分类和预测。即找到一定的函数或者模型来描述和区分数据类之间的区别,用这些函数和模型对未来进行预测。这些数据类是事先已经知道的。分类的结果表示为决策树、分类规则或神经网络。

(4)聚类。即将数据分为多个类,使得类内部数据之间的差异最小,而类之间数据的差异最大。与分类不同的是,聚类前并不知道类的个数。聚类技术主要包括传统的模式识别方法和数学分类学等。

(5)孤立点的检测。孤立点是指数据中的整体表现行为不一致的数据集合。这些数据虽然是一些特例,但往往在错误检查和特例分析中是很有用的。

(6)趋势和演变分析。即描述行为随着时间变化的对象所遵循的规律或趋势。

16.4 大数据时代的新型数据仓库

多年来,作为一种有效的商务智能(BI)解决方案,数据仓库+联机分析处理+数据挖掘(DW+OLAP+DM)架构一直被众多企业所采用,对企业决策进行支持。在大数据时代,由于系统面临的需求在数据量、数据类型、决策分析复杂度和硬件环境等方面发生了质的变化,经典的DW+OLAP+DM架构已经无法胜任新的BI需求,必须对其进行适应性调整。

1.系统需求的变化

和传统的数据仓库相比,大数据时代BI系统面临的需求发生了如下变化:

(1)数据量急剧增长

数据仓库中的数据量由TB级升至PB乃至ZB级,并仍在持续爆炸式增长。据IDC统计,2011 年全球被创建和复制的数据总量为1.8ZB (10^21 数量级)。Google公司每月处理的数据量超过400 PB;百度每天处理的数据量约几十PB; Facebook注册用户超过10亿,每月上传的照片超过10亿张,每天生成300 TB以上的日志数据。

(2)数据类型多样

除了结构化数据之外,大数据时代的数据仓库还必须能够处理大量的半结构化和非结构化数据。包括文本、音频、视频、图片、文字、消息等。数据类型的多样化源于媒介类型的极大丰富。社交网站、在线视频、数码摄像、移动通信、电子商务、遥感卫星等,每天都在源源不断地产生着各种各样的数据。

(3)决策分析复杂

大数据时代,决策分析逐渐由常规分析转向深度分析(deep analytics)。数据分析日益成为企业利润必不可少的支撑点。根据TDWI (The Data Warehousing Institute) 对大数据分析的报告,企业已经不满足于对现有数据的分析和监测,更期望能对未来趋势有更多的分析和预测,以增强企业竞争力。这些分析操作包括诸如移动平均线分析、数据关联关系分析、回归分析、what-if 分析等复杂统计分析,我们统称之为深度分析。

(4)底层硬件环境变化

近年来新硬件技术的发展使计算机处理能力得以提升,多核处理器和众核处理器提供了强大的并行处理能力,大内存提供了更大的存储能力,高速网络更好地优化了网络延迟。数据处理平台由高端服务器转向由中低端硬件构成的大规模机群。由于数据量的迅速增加,数据库/数据仓库的规模不得不随之增大,从而导致其成本的急剧上升。出于成本的考虑,越来越多的企业将应用由高端服务器转向了由中低端硬件构成的大规模机群平台。

2.传统数据仓库所面临的问题

通过上面的论述可以发现,在大数据时代,系统的需求已经发生了根本性的改变。如果继续沿用图16.2所示的抽取+离线存储+分析的分层计算模式会存在如下问题:

(1)数据移动代价过高

在图16.2 所示的数据仓库系统的体系结构中,在数据源层和分析层之间引入了一个存储管理层,虽然可以提升数据质量并针对查询进行优化,但也付出了较大的数据迁移代价和执行时的连接代价:数据首先通过复杂且耗时的ETL过程存储到数据仓库中,在联机分析处理服务器中转化为星形模式或者雪片模式;执行分析时,又通过连接方式将数据从数据库中取出。这些代价在TB级数据量时也许可以接受,但面对大数据,其执行时间至少会增长几个数量级。更为重要的是,对于大量的即席分析,这种数据移动的计算模式是不可取的。

(2)不能快速适应变化

传统的数据仓库假设主题是较少变化的,其应对变化的方式是对数据源到前端展现的整个流程中的每个部分进行修改,然后再重新加载数据,甚至重新计算数据,导致其适应变化的周期较长。这种模式比较适合对数据质量和查询性能要求较高而不太计较预处理代价的场合。但在大数据时代,分析处在变化的业务环境中,这种模式将难以适应新的需求。

因此,在大数据时代,海量数据与系统的数据处理能力之间产生了一个鸿沟:一边是至少PB级的数据量,另一边是面向传统数据分析能力设计的数据仓库和各种商务智能工具。如果这些系统或工具发展缓慢,这个鸿沟将会随着数据量的持续爆炸式增长而逐步拉大。虽然传统数据仓库可以采用舍弃不重要数据或者建立数据集市的方式来缓解此问题,但毕竟只是权宜之策,并非系统级解决方案;而且舍弃的数据在未来可能会重新使用,以发掘更大的价值。

3.大数据时代的新型数据仓库

为了应对大数据时代系统在数据量、数据类型、决策分析复杂度和底层硬件环境等方面的变化,以较低的成本高效地支持大数据分析,新型的数据仓库解决方案需具备表16.2所示的几个重要特性。

《数据库系统概论》学习笔记_第25张图片

满足上述特性的数据仓库解决方案可以有多种形式,每一种方案都有其优缺点,但其基本思想都是将传统的结构化数据处理和新型的大数据处理集成到一个统一的异构平台中,即共存的策略。

大数据时代一种典型的新型数据仓库体系结构如图16.7所示。在这种体系结构中,Hadoop或NoSQL等大数据处理平台和现有的基于关系数据库管理系统的数据仓库平台通过连接器软件组合在一起,两个平台之间的数据通过连接器进行交换。在这种体系结构中,连接器发挥着类似于JDBC (Java DataBase Connector, Java 数据库连接,是Java语言中用来规范客户端程序如何访问数据库的应用程序接口)的作用。

《数据库系统概论》学习笔记_第26张图片

目前,大部分关系数据库、商务智能工具、NoSQL等软件开发商都提供了自己开发的Hadoop和NoSQL连接器。由于其所处的特殊位置,连接器的性能(主要是传输数据的带宽)也经常会成为系统的瓶颈。

16.5 小结

数据仓库(DW)、联机分析处理(OLAP)和数据挖掘(DM)是作为三种独立的信息处理技术出现的。数据仓库用于数据的存储和组织,OLAP集中于数据的分析,数据挖掘则致力于知识的自动发现。它们都可以分别应用到信息系统的设计和实现中,以提高相应部分的处理能力。由于这三种技术内在的联系性和互补性,将它们结合起来就成为一种新的决策支持系统架构,成为BI的三个支柱。这一架构以数据库中的大量数据为基础,具有如下特点:

(1)在底层的数据库中保存了大量的事务级细节数据。这些数据是整个决策支持系统的数据来源。

(2)数据仓库对底层数据库中的事务级数据进行集成、转换、综合,重新组织成面向全局的数据视图,为决策支持系统提供数据存储和组织的基础。

(3)联机分析处理从数据仓库中的集成数据出发,构建面向分析的多维数据模型,再使用多维分析方法从多个不同的视角对多维数据进行了分析、比较。分析活动从以前的方法驱动转向了数据驱动,分析方法和数据结构实现了分离。

(4)数据挖掘以数据仓库和数据库中的大量数据为基础,自动发现数据中的潜在模式,并以这些模式为基础自动地进行预测分析。数据挖掘表明知识就隐藏在日常积累下来的大量数据之中,仅靠复杂的算法和推理并不能发现知识,数据才是知识的源泉。

大数据时代,系统面临的需求在数据量、数据类型、决策分析复杂度和底层硬件环境等方面发生了巨大变化。为了应对这些变化,新型数据仓库通常采用共存的策略,即将传统的结构化数据处理和新型的大数据处理集成到一个统一的异构平台中。

你可能感兴趣的:(数据库)