数据库学习基础篇①

基础篇内容

一、绪论
二、关系数据库
三、关系数据库标准语言


绪论

数据库系统概述

一、基础概念

  1. 数据
    数据是数据库存储的基本对象,有多种表现形式。数据的表现形式还不能完全表达其内容,需要经过解释,数据的解释是指对数据含义的说明,数据的含义成为数据的语义,数据和他的语义是不可区分的。

  2. 数据库(database,简称DB)
    是存放数据的仓库,按照一定的格式存放的。严格来说,数据库是长期存储在计算机内,有组织、可共享的大量数据的集合。数据库中的数据按照一定的数据模型组织、描述和储存,具有较小的冗余度、较高的数据独立性和易扩展性、并可为各种用户共享。
    具有三个基本特点:永久存储、有组织、可共享

  3. 数据库管理系统(database management system ,DBMS)
    DBMS的作用就是科学的组织和存储数据,高效的获取和维护数据。
    主要功能包括了

    1. 数据定义功能:提供数据定义语言来对数据对象进行定义
    2. 数据组织、存储和管理: 基本目标是提供存储空间利用率和方便存取,提供多种方法(如索引查找,hash查找、顺序查找等)来提供存取效率
    3. 数据操纵功能:通过数据操纵语言对数据库进行基本操作,如查询,插入,删除和修改等。
    4. 数据库的事务管理和运行管理:数据库在建立、运用和维护时对数据库管理系统统一管理、控制、以保证数据的安全性、完整性、多用户对数据的并发使用及发生故障后的系统恢复。
    5. 数据库的建立和维护功能:包括了数据库初始数据的输入,转换功能,数据库的转储、恢复功能,数据库的重组织功能和性能监视、分析功能等。
    6. 其他功能:DBMS与网络中其他软件系统的通信功能;一个DBMS与另一个DBMS或文件系统的数据转换功能;异构数据库之间的互访和互操作功能等。
  4. 数据库系统(database system,DBS)
    数据库系统是指计算机系统中引入数据库后的系统,一般由数据库、数据库管理系统、应用系统、数据库管理员构成。


二、 数据库系统的特点

  1. 数据结构化
    这是一个主要特征之一。所谓的“整体”结构化是指数据库的数据不再仅仅针对某一个应用,而是面向全组织;不仅数据内部是结构化的,而且整体也是结构化的,数据之间是具有联系的。在数据库系统中,不仅数据是整体结构化,而且存取数据的方式也很灵活,可以存取数据库中的某一个数据项、一组数据项、一个记录或一组记录。

  2. 数据的共享性高,冗余度低,易扩充
    数据是面向整个系统,可以被多个用户多个应用共享使用,数据共享可以大大减少数据冗余,还能避免数据之间的不相容性和不一致性。
    数据不一致性是指同一数据由于人工管理或者文件系统管理时,重复存储,导致不同拷贝的值不一样。

  3. 数据独立性高
    数据的物理独立性:是指用户的应用程序与存储在磁盘上的数据库中数据是相互独立的。即,数据在磁盘上怎样存储由DBMS管理,用户程序不需要了解,应用程序要处理的只是数据的逻辑结构,这样当数据的物理存储改变了,应用程序不用改变。
    逻辑独立性:是指用户的应用程序与数据库的逻辑结构是相互独立的,即,当数据的逻辑结构改变时,用户程序也可以不变。
    数据独立性由DBMS的二级映像功能来保证。

  4. 数据由DBMS统一管理和控制
    数据库的共享是并发共享,即多个用户可以同时存取数据库中的数据甚至同时存储同一个数据。
    所以DBMS还提供以下几个数据控制功能:
    (1)数据的安全性保护
    (2)数据的完整性检查
    (3)并发控制
    (4)数据库恢复

总结:数据库是长期存储在计算机内有组织的大量的共享的数据集合。它可以提供各种用户共享,具有最小冗余度和较高的数据独立性。


数据模型

数据模型是现实世界数据特征的抽象

数据模型应该满足三个方面:比较真实的模拟现实世界;二是容易为人所理解;三是便于在计算机实现。

根据不同的目的,可以把模型划分两类:

  • 概念模型:也称为信息模型,按照用户的观点来对数据和信息建模,主要用于数据库设计
  • 逻辑模型和物理模型:逻辑模型主要包括层次模型,网状模型,关系模型,面向对象模型和对象关系模型等。是按照计算机系统的观点对数据建模。主要用于DBMS的实现。物理模型是对数据最底层的抽象,描述数据在系统内部的表示方法和存取方法,是面向计算机系统的。物理模型的具体实现是DBMS的任务,数据库设计人员要了解和选择物理模型,一般用户则不需要考虑物理级的细节。

数据模型的组成要素

一般来说,数据模型是严格定义一组概念的集合,这些概念精确地描述了系统的静态特性,动态特性和完整性约束条件。因此数据模型通常由数据结构,数据操作和完整性约束三部分来组成。


一、 数据结构
数据结构描述数据库的组成对象以及对象之间的联系。有两类:

  1. 是与对象的类型,内容,性质有关的,例如网状模型中的数据项,记录,关系模型中的域,属性,关系等。
  2. 是与数据之间的联系有关的对象,例如网状模型中的系型。

二、 数据操作

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

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

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


三、 数据的完整性约束条件

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

数据模型应该反映和规定本数据模型必须遵守的基本的通用的基本的通用的完整性约束条件。

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


概念模型

概念模型一方面应该具有较强的语义表达能力,能够方便、直接的表达应用中的各种语义知识、另一方面应该简单,清晰,易于用户理解。

基本概念

(1) 实体:客观存在并可相互区别的事物成为实体。可以是具体的人事物,也可以是抽象的概念或者联系,比如老师和学校的工作关系。

(2)属性:实体所具有的某一特性称为属性。一个实体可以由若干的属性来刻画,比如学生这个实体可以由学号姓名性别出生年月等信息组成。

(3)码:唯一标识实体的属性集称为码。比如学号是学生实体的码。

(4)域:属性的取值范围称为该属性的域,比如学号的域为8位整数,姓名的域为字符串集合,学生年龄的域为整数,性别的域为(男,女)

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

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

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


实体型之间的联系

一、两个实体型的联系分为三种:

  1. 一对一联系(1:1)
    如果对于实体集A中每一个实体,实体集B中至多有一个(也可以没有)实体与之联系,则称为一对一联系。比如电影院座位和观众实体之间的联系

  2. 一对多联系(1:n)
    如果对于实体集A中每一个实体,实体集B中有n个实体(n>=0)与之联系,比如部门和员工两个实体集之间的联系。

  3. 多对多联系(n:n)
    表示实体集A中多个实体可与实体集B中多个实体相联系。例如一门课程可以同时有若干学生选修,而一个学生也可以同时选修多门课程,这就是多对多联系。
    实际上,一对一联系是一对多联系的特例,而一对多联系又是多对多联系的特例。


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

一般来说,两个以上的实体型也存在一对一,一对多,多对多的联系
比如 课程,老师,参考书 。一个课程可以由若干个老师讲授,也可以使用若干本参考书,这就是一对多。
供应商与项目,零件的联系,一个供应商可以供给多个项目多种零件,而且每个项目可以使用多个供应商供应的零件,每种零件可由不同的供应商攻击。所以是多对多联系。


三、 单个实体型内的联系

同一个实体集内的各实体之间也可以存在一对一,一对多,多对多的联系。
比如职工内部也存在领导与被领导的关系,而一个职工仅被另一个职工直接领导,这是一对多的联系


四、概念模型的一种表示方法:实体—联系方法

概念模型的方法挺多,最著名的是实体-联系方法(entity-relationship Approach)。该方法用E-R图来描述现实世界的概念模型,也称为E-R模型

E-R图提供表示实体型、属性和联系的方法:

  • 实体型 :用矩阵表示,矩形框内写明实体名
  • 属性:用椭圆表示,并用无向边将其相应的实体型连接起来

例如 :学生实体具有学号、姓名、性别、出生年份、系、入学时间等属性,用E_R图表示如下

  • 联系:用菱形表示,菱形框内写明联系名,并用无向边分别与有关实体型连接起来,同时在无向边旁边表上联系的类型(1:1,1:n或m:n)

如果联系具有属性,那么这些属性也需要用无向边和该联系连接起来


五、 一个实例

下面用E-R图来表示某个工厂物资管理的概念模型

物资管理设计的实体有:

  • 仓库 —-属性有仓库号,面积,电话号码
  • 零件 —-属性有零件号,名称,规格,单价,描述
  • 供应商—-属性有供应商号,姓名,地址,电话号码,账号
  • 项目 —-属性有项目号,预算,开工日期
  • 职工 —-属性有职工号,姓名,年龄,职称

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


最常用的数据模型

目前最常用的逻辑数据模型有:

  • 层次模型
  • 网状模型
  • 关系模型
  • 面向对象模型
  • 对象关系模型

其中层次模型和网状模型称为非关系模型,在非关系模型中,实体用记录表示,实体的属性对应记录的数据项(或字段)。实体之间的联系在非关系模型中转换成记录之间的两两联系。

非关系模型

非关系模型中的数据结构的单位是基本层次联系,就是指两个记录及他们之间的一对多(包括一对一)的联系。
如图

Ri位于联系Lij的始点,称为双亲节点,Rj位于联系Lij的终点,称为子女节点


层次模型

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

一、层次数据模型的数据结构

满足下面两个条件的集合为层次模型

(1)有且只有一个节点,没有双亲节点,这个节点称为根节点
(2)根以外的其他节点有且只有一个双亲节点。

在层次模型中,每个节点表示一个记录模型,记录(类型)之间的联系用节点之间的连线(有向边)表示,这种联系是父子之间的一对多的联系。

每个记录模型可包含若干个字段,记录类型描述的是实体,字段描述实体的属性,各个记录类型及其字段都必须命名。各个记录类型、同一个记录类型里的各个字段不能同名。

下图是一个教员学生层次模型,有4个记录型,其中记录型— 系 是根节点,由系编号,系名,办公地点三个字段组成。两个子女节点教研室和学生。记录型— 教研室 是系的子女节点,同时又是教员的双亲节点。由教研室编号,教研室名两个字段组成。记录型— 学生 由学号,姓名,成绩三个字段组成。记录型— 教员由职工号,姓名,研究方向三个字段组成。学生和教员是叶节点,他们没有子女节点。由系到教研室,由教研室到教员,由系到学生均是一对多的联系。

下图是上图对应的一个值,该值是D02系记录值及其所有后代记录值组成的一棵树。


二、 多对多联系在层次模型中的表示

如果用层次模型表示多对多联系,必须首先将多对多联系分解成一对多联系。分解方法两种:冗余节点法和虚拟节点法

下图是简单的多对多,一个学生可以选修多门课程,一门课程可由多个学生选修,学生由学号,姓名,成绩三个字段组成。课程由课程号两个字段组成。

下图是采用冗余节点法,通过增加两个冗余节点将多对多联系转换成两个一对多联系

下图是采用虚拟节点的分解方法,将冗余节点换成虚拟节点,所谓虚拟节点就是一个指针,指向所代替的节点。

冗余节点法的优点是结构清晰,允许节点改变存储位置,缺点需要额外空间,并有潜在的不一致性问题。虚拟节点的优点在减伤空间的浪费吗,避免产生潜在不一致性,缺点是节点改变了存储位置可能引起虚拟节点中指针的修改。


三、层次模型的数据操纵与完整性约束

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

在进行插入操作的时候,如果没有相应的双亲节点就不能插入它的子女节点值,比如在上面的教员学生层次模型中,若新加入一名教员,但是还没分配教研室,这就就不能插入到数据库中。

在进行删除操作时,如果删除双亲节点,那么双亲节点下的子女节点值也被同时删除。在教员学生层次模型中,删除教研室,那么该教研室的教员的数据也会全部丢失。

四、层次数据模型的存储结构

层次数据库中不仅要存储数据本身,还要存储数据之间的层次联系。层次模型数据的储存常常是和数据之间的储存结合在一起的,常用方法有两种

  1. 邻接法
    按照层次树穿越的顺序把素有记录值依次邻接存放,即通过物理空间的位置相邻来体现(或隐含)层次顺序。
  1. 链接法
    用指针来反映数据之间的层次联系。

子女-兄弟链接法:每个记录设两类指针,分别指向最左边的子女(每个记录型对应一个)和最新的兄弟。

层次序列链接法:按照树的前序穿越链接各记录值

五、层次模型的优缺点

优点:

  1. 层次模型的数据结构比较简单清晰
  2. 层次数据库的查询效率高
    层次数据库的性能优于关系数据库,不低于网状数据库
  3. 层次数据模型提供了良好的完整性支持

缺点:

  1. 现实世界很多是非层次性的,如节点之间具有多对多联系
  2. 一个节点如果具有多个双亲等,层次模型表示这类联系方法就很笨拙。
  3. 查询子女节点必须通过双亲节点
  4. 由于结构严密,层次命令趋于程序化

网状模型

由于很多联系是非层次的,用层次模型表示非树形结构是很不直接的,而网状模型则可以克服这个问题。

一、 网状数据模型的数据结构
满足以下两个条件则称为网状模型:
(1)允许一个以上的节点无双亲
(2)一个节点可以有多余一个的双亲

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

网状模型中每一个节点表示一个记录类型(实体),每个记录类型可包含若干个字段(字体的属性),节点间的连线表示记录类型(实体)之间的一对多的父子联系。在层次模型中,子女节点和双亲节点的联系是唯一的,而在网状模型中的是可以不唯一的。

下面是网状模型的例子

以学生选课为例:

  • 一个学生可以选修若干门课程,某一课程可以被多个学生选修,因此学生与课程之前是多对多联系。为了表示多对多的联系,引入了一个学生选课的联结记录,由三个数据项组成,即学号,课程号,成绩,表示某个学生选修某一门课程及其成绩。
  • 学生选课就包含了三个记录,学生、课程、选课
  • 每个学生可以选多门课程,即对学生记录中的一个值,选课记录中可以多个值相联系,而选课记录中的一个值,只能和学生记录中的一个值联系。学生和选课之间的联系是一对多的联系。联系名为S-SC。同样课程与选课的联系也是一对多的联系。联系名为C-SC 。

下图是一个学生,选课,课程的网状数据库的一个值


二、 网状数据模型的操纵和完整性约束

DBTG在模式DDL中提供了定义DBTG数据库完整性的若干概念和语句:
(1)支持记录码的概念,码即唯一表示记录的数据项的集合。例如学生记录中的学号是码,因此不允许学生记录中出现重复的学号。
(2)保证一个联系中双亲记录和子女记录之间是一对多的联系。
(3)可以直接双亲记录和子女记录的某些约束条件。比如有些子女记录要双亲记录存在才可以插入,双亲记录删除也会连同删除。

三、网状数据模型的存储结构

最常用的是链接法,包括单向链接,双向链接,环状链接和向首链接,此外还有其他方法:引元阵列法,二进制阵列法,索引法,根据具体情况来使用。

设一个网状数据库的实例:

  • 学生记录:S1 , S2 , S3;
  • 课程记录:C1 , C2 , C3;
  • S1的选课记录: S1C1A 、S1C2A;
  • S2的选课记录: S2C1A 、S2C3B;
  • S3的选课记录: S3C1B 、S3C2B
  • S4的选课记录: S4C1A 、S4C2A 、S4C3B
  • 学生选课数据库中 学生、课程、选课三个记录的值可以分别按某种文件组织方式存储,记录之间的联系用单向链接实现

  • 图中的实线链表示S-SC联系,即把S1学生和他的选课记录(选修的C1,C2两门课程的选课记录)链接起来,同样把S2,S3,S4学生和他们的选课记录链接起来;

  • 虚线表示C-SC联系,把C1课程和选修了C1课程的学生记录(有S1,S2,S3,W4学生选修了C1)链接起来,同样把C2,C3课程和选修了这些课程的学生记录链接起来。

四、网状数据模型的优缺点

优点:

  1. 能够更直接的描述现实世界,比如一个节点可以有多个双亲,节点之间可以有多重联系
  2. 具有良好的性能,存取效率较高

缺点:

  1. 结构比较复杂,随着应用环境的阔达,数据库的结构变得越来越负责,不利于最终用户掌握。
  2. 网状模型的DDL,DML复杂,并且要嵌入某一种高级语言(COBOL ,C)。用户不容易掌握,不容易使用。
  3. 由于记录之间的联系是通过存取路径实现的,应用程序在访问在访问数据时必须选择适当的存取路径,因此用户必须了解系统结构的细节,家中了编写应用程序的负担。

关系模型

关系模型是目前最重要的一种数据模型。关系数据莫系统采用关系模型作为数据的组织方式。

一、 关系数据模型的数据结构

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

  • 关系(relation):一个关系对应通常说的一张表,如学生登记表
  • 元祖(tuple): 表中的一行即为一个元祖;
  • 属性(Attribute):表中的一列即为一个属性,给每一个属性起一个名称即为属性名。如这张表有6列,对应六个属性(学号,姓名,年龄,性别,系名,年级)
  • 码(key):也称为码键。表中某个属性组,它可以唯一确定一个元祖,如表中的学号可以确定一个学生,也就称为本关系的码
  • 域(domain):属性的取值范围,如人的年龄一般在1~150岁之间,大学生年龄属性域是(14~38),性别的域是(男,女),系名的域是一个学校所有系名的集合;
  • 分量:元祖中的一个属性值
  • 关系模式:对关系的描述,一般表示为
    • 关系名(属性1,属性2,…… ,属性n)

上面的关系可以描述为

  • 学生(学号,姓名,年龄,性别,系名,年级)

在关系模型中,实体以及实体间的联系都是用关系来表示。例如,学生,课程,学生与课程之间的多对多联系在关系模型中可以如下表示:

  • 学生(学号,姓名,年龄,性别,系名,年级)
  • 课程(课程号,课程名,学分)
  • 选修(学号,课程号,成绩)

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

下图是一个术语的粗略对比


二、 关系数据模型的操纵和完整性约束

主要操作:查询,插入,删除和更新数据。

完整性约束包含三大类:实体完整性,参照完整性,用户定义完整性

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

三、关系数据模型的存储结构

在关系数据模型中,实体及实体间的联系都用表来表示,在关系数据库的物理组织中,有的DBMS 一个表对应一个操作系统文件,有的DBMS从操作系统获得若干大的文件,自己设计表、索引等存储结构。

四、关系数据模型的优缺点
优点:

  1. 关系模型与非关系模型不同,是建立在严格的数学概念的基础上
  2. 关系模型的概念单一,无论实体还是实体之间的联系都用关系来表示。对数据的检索和更新结果也是关系(即表)所以其数据结果简单、清晰、用户易懂易用。
  3. 关系模型的存取路径对用户透明,从而更有更高的数据独立性、更好的安全保密性,也简化了程序员的工作和数据库开发建立的工作。

缺点:

  1. 由于存取路径透明,查询效率往往不如非关系数据模型。

数据库的系统结构

本章学习的是数据库系统的模式结构

数据库系统模式的概念

在数据模型中有“型”(T)和“值(value)”的概念。型是指对某一类数据的结构和属性的说明,值是型的一个具体赋值。例如学生记录定义为(学号,姓名,性别,系别,年龄,籍贯)这样的记录型,而(900201,李明,男,计算机,22,江苏)则是该记录型的一个记录值

模式是数据库中全体数据的逻辑结构和特征的描述,仅仅涉及到型的描述,不涉及到具体的值。模式的一个具体值称为模式的一个实例。同一个模式可以有很多实例。

模式是相对稳定的,而实例是相对变动的,因为数据库的数据是不断更新的,模式反应的是数据的结构和联系,而实例反映的是数据库某一时刻的状态。

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

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

模式(Schema)

  1. 模式也叫逻辑模式,是数据库中全体数据的逻辑结构和特征的描述,是所有用户的公共数据视图。属于数据库系统模式结构的中间层,既不涉及数据的物理存储细节和硬件环境,也与具体的应用无关。

  2. 模式实际上是数据库数据在逻辑级上的视图。一个数据库只有一个模式。数据库模式以某一种数据模型为基础,考虑所有用户的需求,结合成一个逻辑整体。

  3. 定义模式时要定义数据的逻辑结构,比如数据记录是由哪些数据项构成,数据项的名字、类型、取值范围等,而且要定义数据之间的联系,定义与数据有关的安全性、完整性要求。

外模式(External Schema)

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

  2. 外模式通常是模式的子集。一个数据库可以有多个外模式,。对模式中的同一数据,在外模式中的结构、类型、长度、保密级别都可以不同。同一个外模式可以被某一个用户的多个应用系统使用,但是一个应用程序只能使用一个外模式。

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

内模式(Internal Schema)

内模式也称为存储模式(Storage Schema),一个数据库只有一个内模式,是数据物理结构和存储方式的描述,是数据在数据库内部的表示方式。例如,记录的存储方式是顺序结构存储还是B树结构存储;索引按什么方式组织;数据是否压缩,是否加密;数据的存储记录结构有何规定等。

粗略的表达:内模式就是存储如表在哪个表空间在哪里有索引,表空间的数据文件放在哪里,在哪个磁盘。


数据的二级映像和功能和数据独立性

数据库系统的三级模式是对数据的三个抽象级别,为了在系统内部实现这三个抽象层次的联系和转换,提供了两层映像:

  • 外模式/模式 映像
  • 模式 / 内模式 映像

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

外模式/模式 映像

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

当模式改变时,由数据库管理员对每个 外模式/模式映像进行改变,可以使外模式不变,从而不必修改应用程序。保证了数据与程序的逻辑独立性。

模式/内模式映像

数据库只有一个模式,也只有一个内模式,所以模式/内模式映像是唯一的,定义了数据全局逻辑结构与存储结构之间的对应关系。例如说明逻辑记录和字段在内部是如何表示的。该映像定义一般包含在模式描述中。

当数据库的存储结构改变了,数据库管理员对模式/内模式映像作相应改变,就可以使模式保持不变,从而应用程序也不必改变。保证了数据与程序的物理独立性。

三种模式的归纳:

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

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

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


数据库系统的组成

大概分为

  1. 硬件平台及数据库:
    • 大内存
    • 大磁盘
    • 系统具有较高的通道能力
  2. 软件:
    • DBMS
    • 支持DBMS的操作系统
    • 具有数据库接口的高级语言
    • 以DBMS为核心的应用开发工具
    • 为特定应用环境开发的数据库应用系统
  3. 人员
    • 数据库管理员
    • 系统分析员和数据库设计人员
    • 应用程序员
    • 用户

关系数据库

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

关系数据结构

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

  1. 域(domain)
    域是一组具有相同数据类型的集合

  2. 笛卡儿积(Cartesian product)
    给定一组域D1,D2, … … ,Dn,这些域可以相同

  1. 关系(relation)

当n=1时,称该关系为单元关系
当n=2时,称为二元关系

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

  • 候选码(Candidate Key): 关系中可以唯一地标识一个元组的 属性 或 属性组。
  • 主码(Primary Key): 若一个关系又多个候选码,则选定其中一个为主码。
  • 主属性(Non-Key attribute):包含在任何候选码中的诸属性称为主属性。不包含在任何候选码中的属性称为非码属性。
  • 外码(Froregin Key): 如果关系模式 R 中的属性或者属性组非该关系的码,但是它是其他关系的码,那么该属性集对关系模式 R而言是外码。
  • 全码(All-Key):关系模型的所有属性组是这个关系模式的候选码,称为全码。

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

关系有三种类型:基本关系(基本表或基表)、查询表、视图表

  • 基本表是实际存在的表,是实际存储数据的逻辑表示。
  • 查询表是查询结果对应的表
  • 视图表是由基本表或者其他视图表到处的表,是虚表,不对应实际存储的数据

基本关系具有六条性质:

  • 列的同质性
  • 列名唯一性
  • 列序无关性
  • 元祖相异性
  • 行序无关性
  • 分量原子性

在实际关系数据库产品中,不一定完全会具备这几条性质

关系模式

关系模式是型,关系是值

关系的描述称为关系模式 ,形式化表示为R(U,D,DOM,F)
其中R为关系名,U为组成该关系的属性名集合,D为属性组U中的属性所来自的域,DOM为属性向域的映像集合,F为属性间数据的依赖关系集合

关系数据库

关系数据库的型也称为关系数据库模式,是对关系数据库的描述。
关系数据库模式包括:

  • 若干域的定义
  • 在这里域上定义的若干关系模式

关系操作

关系模型给出了关系操作能力的说明,但不对RDBMS给出具体的语法要求,也就是说不通的RDBMS可以定义和开发不通的语言来实现这些操作。

基本的关系操作

通常分为两大操作:

  • 查询(query)
  • 插入(insert)、删除(delete)、修改(update)

关系的查询表达能力很强,是关系操作中最主要的部分。

查询操作又可以分为:选择(select)、投影(project)、链接(join)、除(divide)、并(union)、交(intersection)、笛卡尔积等
其中选择,投影,并,差,笛卡尔积是5种基本操作,其他操作可以由基本操作来定义和导出的。

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

关系数据语言分类

早期是用代数方式或逻辑方式表示,称为关系代数和关系演算

关系代数,元祖关系演算和域关系演算均为抽象的查询语言,跟具体的RDBMS中实现的语言不完全一样。

一种介乎于关系代数和关系演算之间的语言SQL,具有丰富的查询功能,还具有数据定义和数据控制功能,是集合了查询、DDL、DML和DCL于一体的关系数据语言。


关系的完整性

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

关系的三类完整性约束

实体完整性

规则:若属性(一个或一组属性)A是基本关系R的主属性,那么A不能取空值

所谓空值就是“不知道”或“不存在”的值

规则说明:

  • 实体完整性是针对基本关系而言的
  • 现实世界的实体是可区分的,即他们具有某种唯一标识
  • 关系模型中以主码作为唯一标识
  • 主码中的属性即主属性不能取空值。

参照完整性

  1. 关系间的引用:在关系模型中实体及实体间的联系都是用关系来描述的,因此可能存在关系与关系间的引用。

  2. 外码

    • 设FALSE是基本关系R 的一个或一组属性,但不是关系R 的码。如果F与基本关系s的主码Ks相对应,则称F为基本关系R的外码
    • 基本关系R称为参照关系
    • 基本关系S称为被参照关系或目标关系
    • 关系R和关系S不一定是不同的关系
  • 显然目标关系S的主码Ks和参照关系R的外码F必须定义在同一个(或同一组)域上。

  • 注意的是,外码不一定要和相应的主码同名,不过在实际中,为了便于识别,尽量取相同的名字。

所以参照完整性规则就是定义外码和主码之间的引用规则

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

  • 或者取空值(F的每个属性值均为空值)
  • 或者等于S中某个元祖的主码值

具体如图

用户定义的完整性

不同的数据库系统根据应用环境的不同,还需要特殊的约束条件,而用户定义的完整性就是针对某一具体关系数据库的约束条件。

  • 针对某一具体关系数据库的约束条件,反应某一具体应用的所涉及的数据必须满足的语义要求
  • 关系模型应提供定义和检验这类完整性的机制,以便用统一的系统的方法去处理它们,而不要用程序来承担这一个功能

关系代数

关系代数是一种抽象的查询语言,
运算对象,运算符,运算结果是运算的三大要素
关系代数的运算对象是关系,运算结果也是关系
运算符包括四类:集合运算符,专门的关系运算符,算术比较符,逻辑运算符。

关系代数的运算按运算符的不同可分为传统的集合运算符和专门的关系运算符。其中集合运算符是把关系看成元祖的集合。专门的关系运算符不仅涉及行还涉及列。比较运算符和逻辑运算符是用来辅助专门的关系运算符进行操作的。

传统的集合运算

  1. 并(Union)
    关系 R 与 S 具有相同的关系模式,即 R 与 S 的元数相同(结构相同),R 与 S 的并是属于 R 或者属于 S 的元组构成的集合,记作 R ∪ S,定义如下:

    R∪S = {t | t∈R ∨ t∈S}
  2. 差(Difference)
    关系 R 与 S 具有相同的关系模式,关系 R 与 S 的差是属于 R 但不属于 S 的元组构成的集合,记作 R − S,定义如下

    R−S = {t | t∈R∨t∉S}
  3. 交(Intersection)
    关系R和关系S交由即属于R又属于S的元组组成, 其结果仍为n目关系

    R∩S = {t | t∈R ∧ t∈S }
  4. 笛卡尔积(cartesian product)
    两个无数分别为 n 目和 m 目的关系 R 和 S 的 笛卡尔积是一个 (n+m) 列的元组的集合。组的前 n 列是关系 R 的一个元组,后 m 列是关系 S 的一个元组,记作 R × S,定义如下:

    R×S = { t | t =< (tn,tm) ∧ tn∈R ∧ tm∈S}

专门的关系运算

专门的运算关系包括 选择、 投影、连接 、 除运算等。

先做几个记号

目=列数,n目或者n度指的是关系表有n个属性,也就是有n列

  1. 选择(selection)
    定义:在关系R中选出满足指定条件F的元组(行操作)
    表达式:σF(R) = {t | t∈R ∧ F(t)=’真’},
    逻辑表达式F的基本形式为:X1 θ Y1
    其中 θ 表示比较运算符或者逻辑运算符,X1、Y1等是属性名或常量或简单函数,而属性名也可以用它的序号来代替
    比较运算符:
    ① : > 大于
    ② : ≥ 大于等于
    ③ : < 小于
    ④ : ≤ 小于等于
    ⑤ : = 等于
    ⑥ : <> 不等于

    逻辑运算符:
    ┐ 非
    ∧ 与
    ∨ 或

下图查询信息系(is系)全体学生

其中下角标 5 为Sdept的属性序号

  1. 投影(projection)
    定义:从关系R中选出若干属性A组成新关系(列操作)
    表达式:πA(R) = { t[A] | t∈R}
    其中A为R中的属性列
    投影操作是从列的角度进行和运算的
    投影之后不仅取消了原关系的某些列,还可能取消了某些元组,因为取消了某些属性后,就可能出现重复行,所以应该取消这些完全相同的行。
  1. 连接(join)
    定义:从两个关系R和S的笛卡尔积中选取属性间满足指定条件AθB的元组
    表达式:R∞S(AθB) = {t(r)t(s)|t(r)∈R∧t(s)∈S∧t(r)[A]θt(s)[B]}

普通连接

关系R: A B C a b c b a c c a b 关系S: A B C b a  c a b  c c a  b 连接起来: RA RB RC SA SB SC a b c   a b c a b c   b a c a b c   c a b b a c   a b c b a c   b a c b a c   c a b c a b   a b c c a b   b a c c a b   c a b
就是R的第一行不断的加S的第一行,第二行,第三行, R的第二行不断的加以S的第一行,第二行,第三行 一直加下去 拓展关系: 连接分两种:等值连接与自然连接 ①等值连接:指定条件AθB的θ为'= '时 那么就把上面普通连接里面RA和SB相同的保留,其他去掉,而且重复的两行也去掉一行
RA RB RC SA SB SC a b c   b a c a b c   c a b b a c   a b c
②自然连接:在等值连接的基础上去除重复的属性
A B C a b c a b c b a c
  1. 除运算(division)
    定义:设关系R除以关系S的结果为关系T,则T包含所有在R但不在S中的属性及值,且T的元组与S的元组的所有组合都在R中.
    表达式:
    R÷S = {t(r)[X]|t(r)∈R∧π(Y)(S)属于Y(x)},其中Y(x)为x在R中的象集,x=t(r)[X]

上面的演算经过有限次复合后形成的式子称为关系代数表达式


关系演算

分为元组关系演算和域关系演算

元组关系演算语言ALPHA

元组关系演算以元组变量作为谓词变元的基本对象。典型的元组关系演算语言是E.F.Codd提出的ALPHA语言,但这一语言并没有实际实现。现在关系库管理系统INGRES所用的QUEL语言是参会照ALPHA语言研制的,与ALPHA十分相似

基本格式中:操作语句主要有GET、PUT、HOLD、UPDATE、DELETE和DROP六条语句

ALPHA语言语句的基本格式是:

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

工作空间是用户与系统的通信区,它可以用一个字母表示,通常用W表示;表达式用于指定语句的操作对象,它可以是关系名和属性名,一条语句可以同时操作多个关系或多个属性;操作条件是一个逻辑表达式,它用于将操作结果限定在满足条件的元组中,操作条件可以为空;呆以在基本格式的基础上加上排序要求,定额要求等。

一、 检索操作

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

格式: GET 工作空间名 (表达式1) 查询所有被选修的课程号码。
GET W (SC.Cno)

(2) 限定的检索(即带条件的检索)

格式: GET 工作空间名(表达式1) :
操作条件 查询信息系(IS)中年龄小于20岁的学生的学号和年龄。
GET W (Student.Sno, Student.Sage):Student.Sdept=’IS’∧Student.Sage<20

(3) 带排序的检索

格式: GET 工作空间名(表达式1) [:操作条件] DOWN/UP 表达式2
查询计算机科学系(CS)学生的学号、 年龄, 结果按年龄降序排序。
GET W (Student.Sno, Student.Sage): Student.Sdept=‘CS’DOWN Student.Sage

(4) 带定额的检索

格式 : GET 工作空间名(定额)(表达式1)[:操作条件] DOWN/UP 表达式2
取出一个信息系学生的学号。
GET W (1) (Student.Sno): Student.Sdept=’IS’

(5) 用元组变量的检索

  1. 元组变量的含义
    表示可以在某一关系范围内变化(也称为范围变量Range Variable)
  2. 元组变量的用途
    简化关系名:设一个较短名字的元组变量来代替较长的关系名。
    操作条件中使用量词时必须用元组变量。
  3. 定义元组变量
    格式: RANGE 关系名 变量名

一个关系可以设多个元组变量 查询信息系学生的名字
RANGE Student X
GET W (X.Sname):X.Sdept=‘IS’

(6) 用存在量词的检索

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

RANGE SC X GET W (Student.Sname): ΕX(X.Sno=Student.Sno∧X.Cno=’2’)

查询至少选修一门其先行课为6号课程的学生名字
RANGE Course CX
    SC  SCX
GET W (Student.Sname):
∃ SCX (SCX.Sno=Student.Sno∧
∃ CX (CX.Cno=SCX.Cno∧CX.Pcno=’6’))

(7) 带有多个关系的表达式的检索

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

RANGE SC SCX
GET W (Student.Sname, Course.Cname): ∃SCX (SCX.Grade≥90∧SCX.Sno=Student.Sno∧Course.Cno=SCX.Cno)

(8) 用全称量词的检索

查询不选1号课程的学生名字。
RANGE SC SCX
GET W (Student.Sname): ∀SCX(SCX.Sno≠Student.Sno∨SCX.Cno≠’1’)

(9) 用两种量词的检索

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

RANGE Course  CX
    SC  SCX
GET W (Student.Sname) : ∀ CX ∃ SCX (SCX.Sno=Student.Sno ∧ SCX.Cno = CX.Cno)

(10) 用蕴函(Implication) 的检索

查询最少选修了95002学生所选的课程的学生的学号

思路:依次检查每一门课程,看95002是否选了这门课,如果选了,再看看有没有其他学生选了这么课,遍历完后。看看是否存在学生把95002选了的课都选了,如果存在即符合。

RANGE Course CX
    SC SCX
    SC SCY
GET W(Student Sno):∀ CX ( ∃ SCX (SCX.Sno=’95002 ∧ SCX.Cno=CX.Cno)
          → ∃ SCY(SCY.Sno=Student.Sno ∧ SCY.Cno=CX.Cno))

(11) 聚集函数

查询学生所在系的数目。

GET W (COUNT(Student.Sdept))
COUNT函数在计数时会自动排除重复值。

二、更新操作

(1)修改操作
修改操作用UPDATE语句实现,步骤是:

  • 用HOLD语句将要修改的元组从数据库中读到工作空间中 HOLD 工作空间名(表达式1) [:操作条件 ]
  • 用宿主语言修改工作空间中元组的属性
  • 用UPDATE语句将修改后的元组送回数据库中

把95007学生从计算机科学系转到信息系

HOLD W (Student.Sno, Student.Sdetp): Student.Sno=’95007 (从Student关系中读出95007学生的数据)
MOVE ‘IS’ TO W.Sdept (用宿主语言进行修改)
UPDATE W (把修改后的元组送回Student关系)

(2)插入操作

  • 用宿主语言在工作空间中建立新元组
  • 用PUT语句把该元组存入指定关系中 PUT 工作空间名 (关系名)

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

MOVE ‘8’ TO W.Cno
MOVE ‘计算机组织与结构’ TO W.Cname
MOVE ‘6’ TO W.Cpno
MOVE ‘2’ TO W.Ccredit
PUT W (Course)    (把w中的元组插入到制定关系course中)

put语句只对一个关系操作,表达式必须为单个关系名

(3)删除

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

95110学生因故退学, 删除该学生元组。

HOLD W (Student):Student.Sno=’95110’
DELETE W


域关系语言QBE

域关系演算以元组变量的分量(即域变量)作为谓词变元的基本对象。最突出的特点是操作方式,它是一种高度非过程化的基于屏幕表格的查询语言,用户通过终端屏幕编辑程序,以填写表格的方式构造查询要求,而查询的结果也是以表格形式显示。

QEB中用示例元素来表示查询结构可能的情况,示例元素实际上就是域变量。以下就是QEB的操作框架:


本章小结

关系数据库是目前使用最广泛的数据库系统。
关系数据库与非关系数据库的区别:关系系统只有“表”这一种数据结构,而非关系数据库系统还有其他数据结构,以及对这些数据结构的操作。


关系数据库标准语言SQL

SQL—-结构化查询语言,是关系数据库的标准语言,SQL是一个通用的,功能极强的关系数据库语言。

SQL特点

SQL语言之所以能够为用户和业界所接受,并成为国际标准,是因为它是一个综合的、功能极强同时又简捷易学的语言。SQL语言集数据查询、数据操纵、数据定义和数据控制功能于一体,主要特点包括:

  1. 综合统一
    SQL集合数据定义、数据操纵、数据控制于一体,语言风格统一。可以独立完成数据库生命周期中的全部活动

    • 定义关系模式,插入数据,建立数据库
    • 对数据库中的数据进行查询和更新
    • 数据库重构和维护
    • 数据库安全性、完整性控制

      在关系模型中实体和实体间的联系均用关系表示,这种数据结构的单一性带来了数据操作符的统一性,查找、插入、删除、更新等每一种操作都只需要一种操作符

  1. 高度非过程化

  2. 面向集合的操作方式
    SQL采用集合操作方式,不仅操作对象、查找结果可以是元组的集合,而且一次插入、删除、更新操作的对象也可以是元组的集合。

  3. 以同一种语法结构提供多种使用方式
    SQL即使独立的语言,也是嵌入式语言。既可以在终端键盘直接输入SQL命令进行数据库操作,也可以嵌入到高级语言,如C、Java程序中提供给程序员使用。这种统一的语法提供多种不同的使用方式的做法,提供了极大的灵活性与方便性。

  4. 语言简洁,易学易用
    核心功能只有九个动词,如下图所示

SQL基本概念

SQL语言支持关系数据库三级模式结构。其中外模式对应于视图和部分基本表,模式对应于基本表,内模式对应于存储文件。

SQL支持关系数据库三级模式结构,如下:

  • 基本表:独立存储于数据库中的数据表(关系),可有若干个索引。
  • 索引:对表中的属性组进行逻辑上排序,可以加快检索速度。
  • 视图:由基表导出的虚表,数据库中只保存视图的定义。
  • 存储文件:以OS文件的形式保存数据库的表、视图、索引等数据库对象。

学生-课程数据库

学生-课程模式 S-T :

  • 学生表:Student(Sno,Sname,Ssex,Sage,Sdept)
  • 课程表:Course(Cno,Cname,Cpno,Ccredit)
  • 学生选课表:SC(Sno,Cno,Grade)

数据定义

SQL的数据定义功能包括了:


一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
|      |       操作方式             |
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
| 操作对象 |   创建      |  删除    |     修改  |
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一
|  模式  |CREATE SCHEMA |DROP SCHEMA | xxx   |
|  表   |CREATE TABLE  |DROP TABLE   |ALTER TABLE |
|  视图  |CREATE VIEW   | DROP VIEW   | xxx    |
|  索引  |CREATE INDEX  |DROP INDEX  | xxx   |
一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一一


SQL通常不提供修改模式定义、修改视图定义和修改索引定义的操作,如有要修改,只能先删除再重建。

模式的定义和删除

一、定义模式
“模式”是一个数据库的命名空间,一个框架,打个比方:在java中,创建模式相当于创建一个包,而创建表相当于创建一个类,一个类是在某一个包下面进行管理的。在mysql中,创建模式与创建数据库是一样的,也就是create schema <模式名>与 create database <数据库名>是等效的。所以模式的定义与删除语句如下:

create schema <模式名> authorization <用户名>

例如创建一个学生-课程的模式S-T

1
create schema "S-T" authorization wang;//为用户wang创建一个模式S-T

删除模式语句如下:

1
drop schema <模式名> <cascade|restrict>

其中cascade与restrict两者必选其一。

cascade(级联),表示删除模式的同时,把该模式中的所有数据库对象(例如表等)也全部删除。

restrict(限制),表示如果该模式下已经定义了下属的数据库对象(如表、视图等),则拒绝执行该删除语句的执行
还可以在创建模式的时候同时在这个模式定义中进一步创建基本表,视图,定义授权,即:

1
create schema <模式名> authorization <用户名> [<表定义子句> | <视图定义子句> |<授权定义子句>]

例如:

1
2
3
4
5
6
7
CREATE SCHEMA TEST AUTHORIZATION ZHANG
CREATE TABLE TAB1(COL1 SMALLINT,
COL2 INT,
COL3 CHAR(20),
COL4 NUMERIC(10,3),
COL5 DECIMAL(5,2)
}

该语句为用户ZHANG创建了一个模式TEST,并且定义了一个表TAB1

二、删除模式

1
DROP SCHEMA <模式名> < CASCADE | RESTRICT >

其中CASCADE :级联删除。即:删除模式的同时把模式中所有的数据库对象(模式中定义的下属数据库对象)全部删除

RESTRICT:限制删除。即:删除模式时,如果模式中已定义下属数据库对象,则拒绝删除。

这两个必须二选一

1
DROP SCHEMA ZHANG CASCADE

该语句删除了模式ZHANG,同时定义的TAB1也被删除了

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

一、定义基本表

基本格式:

1
2
3
4
CREATE TABLE <表名>(<列名> <数据类型>[列级完整性约束条件] 
[,<列名> <数据类型>[列级完整性约束条件]]
.......
[,<表级完整性约束条件> ]);

例子:执行完语句后,会在数据库中建立一个新的空的“学生”表Student,并将有关“学生”表的定义及有关约束条件存放到数据字典中

1
2
3
4
5
6
7
CREATE TABLE Student
( sno CHAR(9) PRIMARY KEY, /* 列级完整性约束条件,Sno是主码*/
Sname CHAR(20) UNIQUE , /* Sname取唯一值*/
Ssex CHAR(2),
Sage SMALINT,
Sdept CHAR(20)
);

二、数据类型
关系模型中重要的概念是域,每一个属性来自一个域,它的取值必须是域中的值。在SQL中域的概念用数据类型来实现,不同的RDBMS在支持的数据类型不完全相同。
一个属性选用哪种数据类型要根据实际情况来决定,一般考虑两个方面,一是取值范围,二是要什么什么运算。
下面是MySQL 数据类型::文本、数字和日期/时间类型。
Text 类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
CHAR(size):保存固定长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的长度。最多 255 个字符.

VARCHAR(size):保存可变长度的字符串(可包含字母、数字以及特殊字符)。在括号中指定字符串的最大长度。最多 255 个字符。
注释:如果值的长度大于 255,则被转换为 TEXT 类型。

TINYTEXT:存放最大长度为 255 个字符的字符串。

TEXT:存放最大长度为 65,535 个字符的字符串。

BLOB:用于 BLOBs (Binary Large OBjects)。存放最多 65,535 字节的数据。

MEDIUMTEXT:存放最大长度为 16,777,215 个字符的字符串。

MEDIUMBLOB:用于 BLOBs (Binary Large OBjects)。存放最多 16,777,215 字节的数据。

LONGTEXT:存放最大长度为 4,294,967,295 个字符的字符串。

LONGBLOB:用于 BLOBs (Binary Large OBjects)。存放最多4,294,967,295 字节的数据

ENUM(x,y,z,etc.):允许你输入可能值的列表。可以在 ENUM 列表中列出最大 65535 个值。如果列表中不存在插入的值,则插入空值。
注释:这些值是按照你输入的顺序存储的。
可以按照此格式输入可能的值:ENUM('X','Y','Z')

SET:与 ENUM 类似,SET 最多只能包含 64 个列表项,不过 SET 可存储一个以上的值。 |

Number 类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TINYINT(size):-128 到 127 常规。0 到 255 无符号*。在括号中规定最大位数。

SMALLINT(size):-32768 到 32767 常规。0 到 65535 无符号*。在括号中规定最大位数。

MEDIUMINT(size):-8388608 到 8388607 普通。0 to 16777215 无符号*。在括号中规定最大位数。

INT(size):-2147483648 到 2147483647 常规。0 到 4294967295 无符号*。在括号中规定最大位数。

BIGINT(size):-9223372036854775808 到 9223372036854775807 常规。0 到 18446744073709551615 无符号*。在括号中规定最大位数。

FLOAT(size,d):带有浮动小数点的小数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。

DOUBLE(size,d):带有浮动小数点的大数字。在括号中规定最大位数。在 d 参数中规定小数点右侧的最大位数。

DECIMAL(size,d):作为字符串存储的 DOUBLE 类型,允许固定的小数点。
  • 这些整数类型拥有额外的选项 UNSIGNED。通常,整数可以是负数或正数。如果添加 UNSIGNED 属性,那么范围将从 0 开始,而不是某个负数。

Date 类型:

1
2
3
4
5
6
7
8
9
10
11
12
13
DATE() : 日期。格式:YYYY-MM-DD
注释:支持的范围是从 '1000-01-01' 到 '9999-12-31'

DATETIME() : *日期和时间的组合。格式:YYYY-MM-DD HH:MM:SS
注释:支持的范围是从 '1000-01-01 00:00:00' 到 '9999-12-31 23:59:59'

TIMESTAMP() : *时间戳。TIMESTAMP 值使用 Unix 纪元('1970-01-01 00:00:00' UTC) 至今的描述来存储。格式:YYYY-MM-DD HH:MM:SS
注释:支持的范围是从 '1970-01-01 00:00:01' UTC 到 '2038-01-09 03:14:07' UTC

TIME() : 时间。格式:HH:MM:SS 注释:支持的范围是从 '-838:59:59' 到 '838:59:59'

YEAR() : 2 位或 4 位格式的年。
注释:4 位格式所允许的值:1901 到 2155。2 位格式所允许的值:70 到 69,表示从 1970 到 2069。

三、模式与表

每一个基本表都属于某一个模式,一个模式包含多个基本表
定义表所属的模式,有三种方法

  • 方法一:在表明中给出模式名
    CREATE table “S-T”.Student(…..);    / Student所属的模式是S-T/
    CREATE table “S-T”.Course(……);    / Course所属的模式是S-T/
    CREATE table “S-T”.SC(…….);      / SC所属的模式是S-T /

  • 方法二:在创建模式语句中同时创建表,在定义模式的例子里可以看到

  • 方法三:设置所属的模式,这样创建表时不用给出模式名

当用户创建基本表的时候没指定模式,那么系统会搜索路径来确定所属模式,如果路径包含一组模式列表,则使用第一个存在的模式作为对象的模式名。如果路径中的模式名都不存在,系统就给出错误。

四、修改基本表

SQL语言用ALTER TABLE来修改基本表,一般格式为:

1
2
3
4
ALTER TABLE <表名>
[ADD <新列名> <数据类型> [完整性约束]];
[DROP <完整性约束名>];
[ALTER COLUMN<列名> <数据类型>];

<表名>是要修改的基本表,ADD子句用于增加新列和新的完整性约束,DROP子句用于删除指定的完整性约束条件,ALTER COLUMN 子句用于修改原有的列定义,包括列名和数据类型

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

ALETER TABLE Student ADD_S_ENTRANCE DATE;

不论基本表是否原来有数据,新增加的一列均为日期型

五、删除基本表

当某个表不再需要时,用DROP TABLE语句删除它,格式为

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

若选择RESTRICT,则该表的删除是有限制条件,不能被其他表的约束所引用,也不能有视图,触发器,存储过程或函数等

若选择CASCADE,则没有限制条件,删除基本表的时候,相关的依赖对象也会一起删除,例如视图等

缺省的情况的是RESTRICT。

例子:删除Student表

1
DROP TABLE Student CASCADE

基本表定义一旦被删除,不仅表中数据和定义被删除,而且表上建立的索引、视图、触发器等有关对象也一般会被删除。所以执行该操作需要特别小心


索引的建立与删除

建立索引是加快查询速度的有效手段,根据需要,在基本表上建议一个或者多个的索引,以提供多种存取路径,加快查找速度。
但是索引也有不适宜的情况,原因是建立索引后,更新索引上的数据时会导致表中记录的物理顺序的变更,代价较大,且会占用一定的系统资源,因此对于经常更新的列不宜建立索引。

建议建立索引的情况:

  • 主码和外码一般会建立索引
  • 以读为主或只读的表,只要空间允许可以建立多个索引
  • 等值查询,且满足条件的元组数小于总元组数的5%,可以考虑在相关属性上建立索引
  • 范围查询

不建议建立索引的情况:

  • 不出现或很少出现查询的属性
  • 属性值很少的属性
  • 属性值分布严重不均的属性
  • 经常更新的属性或表
  • 过长的属性
  • 太小的表

一般建立与删除索引是有数据库管理员或者表的属主(owner),即建立表的人完成。系统存取数据时自动选择合适的索引作为存取路径,用户不必也不能显式的选择索引 。

一、建立索引

建立索引的一般格式为:

1
2
create [unique][cluster]index<索引名>
on <表名>(<列名>[<次序>][,<列名>[<次序>]]...);

其中,表名是要建立索引的基本表的名字。索引可以建立在一列或多列上,每个<列名>后面还可以用<次序>指定索引值的排列次序,可选ASC(升序)或DESC(降序),缺省值为ASC。
unique表示此索引的每一个索引值只对应唯一的数据记录。
cluster表示要建立的索引是聚簇索引。所谓聚簇索引是指索引项的数据与表中记录的物理顺序一致的索引组织。

例:在Student表上的姓名列建立一个聚簇索引。

1
2
create cluster index Stusname
on Student(Sname);

例:在sc表的Sno(升序), Cno(升序)和grade (降序)三列上建立一个普通索引SCno。

1
2
create index SCno
on table SC(Sno,Cno,Grade DESC);

二、删除索引

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

删除索引的一般格式为:

1
drop index<索引名>;

例:删除Student表上的Stusname索引。

1
drop index Stusname;

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

在RDBMS中索引一般采用B+树,HASH索引来实现,B+树索引具有动态平衡的优点。HSAH索引具有查找速度快的特点。索引是关系数据库的内部实现技术,属于内模式的范畴。

用户使用CREATE INDEX 语句定义索引的时候,可以定义索引是唯一索引、非唯一索引或者聚簇索引。至于某一个索引是采用B+树还是HASH索引则由具体的RDBMS来决定。

数据查询

数据库查询是数据库的核心操作

一般格式为:

1
2
3
4
5
SELECT [ALL | DISTINCT] <目标列表达式>  [,<目标列表达式>]  ...
FROM <表名或者视图名> [,<表名或者视图名>] ....
[WHERE <条件表达式>]
[GROUP BY <列名1>[HAVING <条件表达式>] ]
[ORDER BY <列名2> [ ASC | DESC ] ];

根据where子句的条件表达式,从from子句指定基本表或者视图找出满足条件的元组,再按select子句中的目标列表达式,选出元组的属性值形成结果表

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

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


单表查询

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

一、选择表中的若干列

选择表中的全部列或者部分列,就是关系代数的投影运算

  1. 查询制定列
    在很多情况下,用户只需要一部分属性列,通过在select子句<目标列表达式>中指定要查询的属性列。
    例子1 查询全体学生的学号和姓名。

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

例子2

1
2
SELECT Sname ,Sno ,Sdept
FROM Student;
<目标列表达式>中各个列的先后顺序可以与表中的顺序不一致,根据需要改变列的显示顺序。
  1. 查询全部列
    将表中所有属性列出来,两种方法
    第一种是在关键字后面把所有列都列出来
    第二种就是指定为 * 这个符号。
    例子:查询全体学生详细记录。

    1
    2
    SELECT *
    FROM Student

    等价于

    1
    2
    	SELECT Sno ,Sname,Ssex ,Sage, Sdept
    FROM Studetn;
  2. 查询经过计算的量
    SELECT 子句的<目标列表达式>不仅可以是表中的属性列,也可以是表达式

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

    1
    2
    SELECT Sname ,2004- Sage        /*查询结果的第二列是一个算术表达式*/
    FROM Student;

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

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

    结果为

    Sname    ‘Year of Birth:’    2004-Sage     LOWER (Sdept)
    ————————————————————————————————————
    刘勇    ‘Year of Birth:’     1984        cs
    刘晨    ‘Year of Birth:’     1985        cs
    王敏    ‘Year of Birth:’     1986        ma
    张立    ‘Year of Birth:’     1985        is
    ————————————————————————————————————

    还可以通过指定别名来改变查询结果的列标题
    修改如下

    1
    2
    SELECT Sname ,'Year of Birth:' BIRTH ,2004-Sage BIRTHDAY,LOWER (Sdept) DEPARTMENT
    FROM Student;

    结果为

    Sname     BIRTH        BIRTHDAY     DEPATMENT
    ————————————————————————————————————
    刘勇    ‘Year of Birth:’     1984        cs
    刘晨    ‘Year of Birth:’     1985        cs
    王敏    ‘Year of Birth:’     1986        ma
    张立    ‘Year of Birth:’     1985        is
    ————————————————————————————————————

二、选择表中的若干元组

  1. 消除取值重复的行
    两个本来并不完全相同的元组,投影到制定的某些列上后,就可能变成了相同的行了,可以用DISTINCT取消他们。

例子 查询选修了课程的学生学号

1
2
SELECT Sno
FROM SC;

输出结果为:
  Sno
——————
200215121
200215121
200215121
200215122
200215122

如果为了去掉重复的行,必须制定DISTINCT关键词

1
2
SELECT DISTINCT Sno
FROM SC

输出结果为
  Sno
——————
200215121
200215122

如果没有指定DISTINCT关键词,那么缺省为ALL,则保留结果中重复的行

  1. 查询满足条件的元组
    查询满足指定条件的元组可以通过where子句实现,

                常用的查询条件
——————————————————————————————————————
查询条件             谓词               
——————————————————————————————————————
比较        =,>,<,<=,>=,!=,<>,!>,!<;NOT + 上述比较运算符
确定范围      BETWEEN AND,NOT BETWWEN AND
确定集合      IN, NOT IN
字符匹配      LIKE , NOT LIKE
空值        IS NULL , IS NOT NULL
多重条件(逻辑运算) AND, OR , NOT
——————————————————————————————————————

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

(2)确定范围
谓词BETWEEN…AND….相对谓词是NOT BETWEEN …ADN….

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

1
2
3
SELECT Sname ,Sdept,Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;

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

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

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

(4)字符匹配
谓词LIKE可以用来进行字符串的匹配,一般格式为:
[NOT] LIKE ‘<匹配符>’ [ESCAPE’ <换码字符>’]
其含义是查找指定的属性列值与<匹配串>相匹配的元组。<匹配串>可以是一个完整的字符串,也可以是含有通配符%和 _ 其中:

  • % (百分号)代表任意长度的字符串,例如a%b表示以a开头,以b结尾的任意长度的字符串,如acb、addgb、ab等都满足该匹配
  • _ (下横线)代表任意单个字符,例如 a_b表示以a开头,以b结尾的的长度为3的任意字符串,如acb、adb、asb等都满足。注意的是一个汉字占用两个字符。所以匹配汉字的时候需要两个下横线。

例子 : 查询学号为200212121的学生的详细情况

1
2
3
4
5
6
7
8
9
10
11
SELECT *
FROM Student
WHERE Soo LIKE '200215121'
```

等价于

```sql
SELECT *
FROM Student
WHERE Sno ='200215121'

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

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

例子

1
2
3
SELECT Cno,Ceredit
FROM Course
WHERE Cname LIKE 'DB\_Design' ESCAPE '\' ;

这里就是escape ‘\’表示把’\’表示为转码字符,这样匹配串中紧跟在 ‘\’ 后面的字符 ‘_’ 不在具有通配符的含义
转义为普通的 ‘_’ 字符

(5)涉及空值的查询
例:某些学生选修课程后没有参加考试,所以有选课记录没有考试成绩,查询缺少成绩的学生的学号和相应的课程号

1
2
3
SELECT Sno , Cno
FROM SC
WHERE Grade IS NULLL /* 分数是grade是空值*/

这里的IS不能用 = 来代替

(6)多重条件查询
逻辑运算符AND 和OR可用联结多个查询条件,AND 的优先级高于OR,但用户可以用括号来改变优先级

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

1
2
3
SELECT Sname
FROM Student
WHERE Sdept = 'CS' AND Sage <20;

三、 ORDER BY子句

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

例 查询小选修了3号课程的学生的学号和成绩,查询结果按分数的降序排列

1
2
3
4
SELECT Sno,Grade
FROM SC
WHERE Cno='3'
RODER BY Grade DESC;

对于空值,若按升序排,含空值的元组将最后显示,若按降序排,空值的元组将最先显示。

四、 聚集函数 (aggregate functions)

为了增强检索功能,sql提供许多聚集函数

1 count : 行数

2 sum : 总和 (求总和)

3 avg : 平均值

4 max 最大值

5 min : 最小值

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

1
2
SELECT COUNT (DISTINCT Sno)
FROM SC;

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

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

1
2
3
SELECT AVG (Grade)
FROM SC
WHERE Cno= '1';

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

1
2
3
SELECT SUM(Ceredit)
FROM SC ,Course
WHERE Sno= '200215012' AND SC.Cno=Course.Cno

在聚集函数遇到空值时,除COUNT(*)外,都跳过空值而处理非空值

五、GROUP BY子句

GROUP BY 子句将查询结果按某一列或多列的值分组,值相等的为一组
对查询结果分组的目的是为了细化聚集函数的作用对象,如果未对查询结果分组,聚集函数将作用于整个查询结果。

例子 查询各个课程号及其相应的选课人数

1
2
3
SELECT Cno ,COUNT (Sno)
FROM SC
GROUP BY Cno;

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

查询结果可能为

Cno        COUNT(Sno)
————————————————————————————
 1          22
  2          34
  3          44
  4          33
  5          48
————————————————————————————

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

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

1
2
3
4
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT (*) >3;

先用group by按Sno进行分组,再用聚集函数COUNT对每一组计算。HAVING短语给出了选择组的条件,且只有满足条件(即元组个数>3),表示此学生选修的课超过3门的才会选出来

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

连接查询

若查询同时设计到两个以上的表,则称之为连接查询

连接查询是关系数据库中最主要的查询,包括了等值连接查询,自然连接查询,非等值连接查询,自身连接查询,外连接查询和符合条件连接查询等

一、 等值与非等值连接查询

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

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

其中比较运算符主要有: =、>、< 、 >= 、<=、 != (或<>)

还可以用以下格式:
[<表名1>] <列名1> BETWEEN [<表名2>]<列名2> AND [<表名2>]<列名3>

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

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

例子 查询每个学生及其选修课程的情况

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

1
2
3
SELECT Student *  , SC . *  
FROM Student ,SC
WHERE Student.Sno =SC.Sno; /* 将Student和SC中同一个学生的元组连接起来*/

假设 Student表和SC表的数据如上面 学生-课程数据库的表一样

那么执行结果如下:

Student.Sno  Sname Ssex  Sage  Sdept  SC.Sno  Cno Grade
————————————————————————————————————
200215121  李勇  男   20  CS  200215121   1  92
200215121  李勇  男   20  CS  200215121   2  85
200215121  李勇  男   20  CS  200215121   3  88
200215122  刘晨  女   19  CS  200215122   2  90
200215122  刘晨  女   19  CS  200215122   3  80
————————————————————————————————————

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

RDBMS执行该连接操作的一种可能过程是:
首先在表Student中找第一个元组,就开始扫描SC表,查找与Student第一个元组的Sno相等的SC元组,找到后将Student中第一个元组与该元组拼接起来,形成结果表中的一个元组,SC中全部查找完后,再找Student中第二个元组,不断的重复上述操作。这是嵌套循环算法的基本思想。

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

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

对上例子用自然连接完成。

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

二、自身连接

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

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

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

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

FIRST表(Course表)
——————————————————————————————————————
Cno     Cname      Cpno      Ccredit
  1     数据库        5          4
  2      数学                    2
  3     信息系统       1          4
  4     操作系统       6          3
  5     数据结构       7          4
  6     数据处理                   2
 7     PASCAL         6          4
——————————————————————————————————————

SECOND表 (Course表)
——————————————————————————————————————
Cno     Cname      Cpno      Ccredit
  1     数据库        5          4
  2      数学                   2
  3     信息系统       1          4
  4     操作系统       6          3
  5     数据结构       7          4
  6     数据处理                  2
 7     PASCAL         6          4
——————————————————————————————————————

完成该查询的SQL语句为

1
2
3
SELECT FIRST Cno ,second.Cpno
FROM Course FIRST , Course SECOND
WHERE FIRST Cpno =SECOND.Cno

结果为

Cno    Pcno
————————————
1      7
3      5
5      6

三、外连接

一般来说,只有满足连接条件的元组才会作为结果输出,例如上面的输出结果没有200215123和200215125两个学生的信息,是因为没有选课,在SC中没有相应的元组,在Student这些元组在连接时就被舍弃了。

如果还想以Student表为主体列出每个学生的基本情况及其选课情况,其中某个学生没有选课,仍把舍弃的Student元组保存在结果关系中,而在SC表的属性上填空值(null),这时候就需要外连接。

1
2
3
4
SELECT Student ,Sno, Sname,Ssx,Sage,Sdept,Cno,Grade
FROM Student LEFT OUT JOIN SC ON(Student.Sno = SC.Sno)
/*也可以使用USING来去掉结果中的重复值;
FROM Student LEFT OUT JOIN SC USING (Sno); */

执行结果如下

Student.Sno  Sname Ssex  Sage  Sdept  SC.Sno   Cno  Grade
————————————————————————————————————————
200215121  李勇   男   20  CS  200215121    1     92
200215121  李勇   男   20  CS  200215121    2     85
200215121  李勇   男   20  CS  200215121    3     88
200215122  刘晨   女   19  CS  200215122    2     90
200215122  刘晨   女   19  CS  200215122    3     80
200215123  王敏   女   18  MA  200215122  NULL  NULL
200215125  张立   男   19   IS   200215122  NULL  NULL
————————————————————————————————————————

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

四、复合条件连接

在上面各个连接查询中,where子句中只有一个条件,即连接谓词,where子句中可以有多个连接条件,称为复合条件连接

例 查询选修2号课程且成绩在90分以上的所有学生

1
2
3
4
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中满足连接条件的元组进行连接得到最终的结果关系。

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

查询每个学生的学号、姓名、选修的课程号及成绩
本查询涉及三个表,查询语句如下:

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

嵌套查询

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

1
2
3
4
5
6
SELECT Sname             /*外层查询或者父查询*/             
FROM Student
WHERE Sno IN
(SELECT Sno /* 内层查询或者子查询 */
FROM SC
WHERE Cno='2');

SQL语言支持多层嵌套查询,即一个子查询里还可以嵌套其他子查询。
但是注意:子查询的select语句中不能使用order by子句,order by子句只能对最终查询结果排序。

以层层嵌套的方式来构造程序正是SQL中“结构化”的含义所在。

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

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

先分步完成此查询,然后再构造嵌套查询。
①确定“刘晨”所在系名

1
2
3
SELECT Sdept
FROM Student
WHERE Sname= '刘晨'

结果为:CS

②查找所有在CS系学习的学生

1
2
3
SELECT Sno ,Sname ,Sdept
FROM Student
WHERE Sdept ='CS';

结果为:

Student.Sno  Sname  Sdep
——————————————————
200215121  李勇  CS
200215122  刘晨  CS
——————————————————

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

1
2
3
4
5
6
SELECT Sno , Sname ,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname='刘晨');

这个例子不依赖父查询,所以称为不相关子查询

二、带有比较运算符的子查询

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

比如刚刚上面的例子
查询与“刘晨”在同一个系的学生。
由于一个学生只能在一个系学习,也就是说内查询的结果是一个值,因此可以用‘=’来代替IN

1
2
3
4
5
6
SELECT Sno , Sname ,Sdept
FROM Student
WHERE Sdept =
(SELECT Sdept
FROM Student
WHERE Sname='刘晨');

注意的是子查询一定要跟在比较符之后,下面是错误语法

1
2
3
4
5
SELECT Sno , Sname ,Sdept
FROM Student
WHERE (SELECT Sdept
FROM Student
WHERE Sname='刘晨')=Sdept;

如果子查询条件依赖于父查询,这类子查询称为相关子查询,整个查询语句称为相关嵌套查询语句。

下面是相关嵌套查询

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

1
2
3
4
5
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值(200215121)传送给内层查询
1
2
3
SELECT AVG(Grade)
FROM SC y
WHERE y.Sno='200215121';
  1. 执行内层查询,得到值88(近似值),用该值替代内层查询,得到外层查询
1
2
3
SELECT Sno,Cno
FROM SC x
WHERE Grade ='200215121'
  1. 执行这个查询,得到
    (200215121,1)
    (200215121,3)
    然后外层查询取出下一个元组重复做上述的操作,知道全部处理完毕。结果为
    (200215121,1)
    (200215121,3)
    (200215122,2)

三、带有ANY(SOME)或ALL谓词的子查询

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>  ANY 大于子查询结果中的某个值

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

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

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

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

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

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

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

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

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

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

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

例 : 查询其他系中比计算机科学系某一学生年龄小的学生姓名和年龄

1
2
3
4
5
6
SELECT Sname,Sage 
FROM Student
WHERE Sage < ANY ( SELECT Sage
FROM Student
WHERE Sdept='CS' )
AND Sdept <> 'CS'; /* 这是父查询块中的条件 */

结果如下:
Sname   Sage
——————————
王敏    18
张立    19

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

这个例子也可以用聚集函数实现,SQL如下

1
2
3
4
5
6
7
SELECT Sname ,Sage
FROM Student
WHERE Sage <
(SELECT MIN (Sage)
FROM Student
WHERE Sdept='CS')
AND Sdept <> 'CS';

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

四、带有EXISTS谓词的子查询
EXISTS代表存在量词 ,带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值‘true’或逻辑假值‘FALSE’

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

例 查询所有选修了 1 号课程的学生姓名
该查询设计了Student表和SC表,可以在Student中依次取每个元组的Sno值,用此值去检查SC表,若SC中存在这一的元组,其Sno值等与此Student.Sno值,并且其Cno=‘1’,则取此Student.Sname送入结果表

1
2
3
4
5
6
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno = Student.Sno AND Cno='1');

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

由EXISTS引出的子查询,起目标列表达式通常用 * 号,因为带EXISTS的子查询只返回真价值,给出列名无实际意义。

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

例 : 查询至少选修了学生200215122选修的全部课程的学生号码
本查询可以用逻辑蕴含来表达:查询学号为x的学生,对所有的课程y,只要200215122学生选修了课程y,则x也选修了y,形式化表示如下:
用p表示谓词”学生200215122选修了课程“
用q表示谓词“学生x选修了课程y”
则上述查询为: ( ∀y )p→q

但是SQL语言没有蕴含逻辑运算,但是可以利用谓词演算将一个逻辑蕴含的谓词等价转换为 p → q ≡ ¬ p ∨ q

该查询可以转换为如下等价形式:
( ∀y )p→q ≡ ¬(∃y( ¬(p→q))≡¬(∃y(¬(¬p∨ q)≡ ¬ ∃y(p ∧ ¬q
))))

sql语言表达:

1
2
3
4
5
6
7
8
9
10
11
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno =' 200215122 ' AND
NOT EXISTS
(SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND
SCZ.Cno= SCY.Cno));

 集合查询

SELECT语句的查询结果是元组的集合,所以多个SELECT语句的结果可进行集合操作。集合操作的主要 并操作UNION、交操作INTERSECT和 差操作EXCEPT。
注意,参加集合操作的各查询结果的列数必须相同,对应项的数据类型也必须相同

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

1
2
3
4
5
6
7
SELECT *
FROM Student
WHERE Sdept ='CS'
UNION
SELECT *
FROM Student
WHERE Sage <= 19;

使用UNION将多个查询结果合并起来时,系统会自动去掉重复元组,如果要保留重复元组则用UNION ALL操作符

例 查询选修课程 1 的学生 或 选修课程2 的学生

1
2
3
4
5
6
7
SELECT *
FROM Student
WHERE Cno ='1'
UNION
SELECT *
FROM Student
WHERE Cno ='2'

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

1
2
3
4
5
6
7
SELECT *
FROM Student
WHERE Sdept ='CS'
INTERSECT
SELECT *
FROM Student
WHERE Sage <= 19;

SELECT 语句的一般格式

1
2
3
4
5
SELECT  [ ALLDISTINCT ] < 目标列表达式 > [别名] [,<目标列表达式> [别名]] .......
FROM <表名或视图名> [ 别名 ] [,< 表名或视图名 > [别名]] ......
[WHERE < 条件表达式>]
{GROUP BY <列名1> [ HAVING <条件表达式>]]
[ORDER BY <列名2> [ASCIDESC]];
  1. 目标列表达式有以下可选格式:
    (1)
    (2) <表名>.

    (3) COUNT ([DISTINCT | ALL])
    (4)[<表名>.] <属性列名表达式>[.[<表名>.]<属性列名表达式>]…..
    其中<属性列表达式>可以是由属性列,作用于属性列的聚集函数和常量的任意算术运算(+、-、
    、/)组成的运算公式

  2. 聚集函数一般格式为:

COUNT ↘
SUM   ↘
AVG  →→ ([DISTINCT|ALL]<列名>) 
MAX   ↗
MIN ↗

  1. WHERE子句的条件表达式有以下可选格式

(1)

1
2
3
        <属性列名>
<属性列名> θ < 常量 >
        [ANY | ALL](SELECT 语句)

(2)

1
2
3
                          <属性列名>     <属性列名>
<属性列名> [NOT] BETWEEN <常量>   AND <常量>
(SELECT语句) <SELECT语句>

(3)

1
2
3
  		     ↗(<值1> [,<值2>]....)   
<属性列名> [NOT] IN
↘ (SELECT 语句)

(4)<属性列名> [NOT] LIKE <匹配串>

(5)<属性列名> IS [NOT] NULL

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

(7)

1
2
3
  	    AND                 AND
<条件表达式> [ <条件表达式> <条件表达式>].....
OR OR


数据更新

三种操作:添加,修改,删除

插入数据

SQL插入语句INSERT通常两种形式:插入一个元组,插入子查询结果,其中后者可以一次插入多个元组。

一、 插入元组

格式为:

1
2
3
INSERT
INTO <表名> [ (<属性列1>[,<属性列2>]...)]
VALUES (< 常量1 > [,< 常量2 >]....);

功能是将新元组插入指定表中,INTO子句中没有出现的属性列,新元组将取空值,但是表定义的时候,说明了NOT NULL的属性列不能取空值,否则会出错。
如果INTO子句中没有指明任何属性列名,则新插入的元组必须每个属性列上均有值

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

1
2
3
insert 
into student(sno,sname,ssex,sdept,sage)
values( '200215128' , '陈冬','男' , 'is' , 18 );

属性的顺序可以与CREATE TABLE 中的顺序不一样,VALUES子句对新元组的各属性赋值,字符串常数要用单引号括起来。

例 将学生张成民的信息插入到Student表中信息:‘200215126’ ‘张成民’ ‘男’ 18 ‘CS’

1
2
3
insert 
into student
values( '200115126' , '张成民' , '男' , 'cs' , 18 );

这个与上个例子不同的是没有指明属性名,所以新元组要在所有的属性列上都指定值,并且属性列顺序与CRAETE TABLE上的次序要相同。VALUES子句对新元组的各属性列赋值,一定要注意值与属性列要一一对应,赋值错会造成数据类型不同而出错。

例 插入一条选课记录( ‘200215128’,’1 ‘)

1
2
3
insert 
into SC(Sno,Cno)
values('200215128','1');

RDBMS自动在新插入的记录Grade上赋空值

或者

1
2
3
insert 
into sc
values('200215128','1',NULL);

没有指定出SC的属性名,在Grade列上要明确给出空值

二、 插入子查询结果
子查询不仅可以嵌套在SELECT语句中,用以构造父查询的条件,也可以 嵌套在INSERT语句中,用以生成要插入的批量数据

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

1
2
3
INSERT 
INTO <表名> [(<属性列1> [,<属性列2>]....) ]
子查询;

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

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

1
2
3
create table dept_age
(sdept char(15)
avg_age smllint);

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

1
2
3
4
5
insert
into dept_age(sdept,avg_age)
select sdept,avg(sage)
from student
group by sdept;

修改数据

又称为更新操作 ,一般格式为

1
2
3
UPDATE <表名>
SET <列名> = <表达式> [,<列名> = <表达式> ]....
[WHERE <>];

其功能是修改指定表中满足 WHERE子句条件的元组,其中set子句给出<表达式>的值用子取代相应的属性列值,如果省略where子句,则表示要修改表中的所有元组。

一、 修改某一个元组的值

例 将学生200215121的年龄改为22岁

1
2
3
update student
set sage=22
where sno='200212121';

二、修改多个元组的值

例 将所有的学生年轻增加1岁

1
2
update student
set sage= Sage+1

三、带子查询的修改语句

子查询也嵌套在UPDATE语句中,用以构造修改的条件。
例 将计算机科学系全体学生的成绩置零

1
2
3
4
5
6
update sc
set grade=0
where 'cs'=
(select sdept
from student
where student.sno=sc.sno);

删除数据

格式为:

1
2
3
DELETE 
FROM <表名>
[WHERE <条件>];

DELETE语句功能从指定表中删除满足where子句的所有元组,如果没有指定,那么就删除所有元组,但表的定义仍在字典中,delete语句删除的是表中的数据,而不是关于表的定义。

一、删除某一个元组的值

例 删除学号为200215128的学生记录

1
2
3
DELETE 
FROM Student
WHERE Sno = '200215128'

二、删除多个元组的值

1
2
DELETE 
FROM SC

这条delete语句使SC表变为空表,删除了SC所有元组

三、带子查询的删除语句
子查询同样也可以嵌套在delete语句中,用以构造执行删除操作的条件。
例:删除计算机科学系所有学生的选课记录。

1
2
3
4
5
6
delete 
from sc
where 'cs'=
(select sdept
from student
where student.sno=sc.sno);

视图

视图是从一个或几个基本表(或视图)导出的表。它与基本表不同,是一个虚表。数据库中只存放视图的定义,而不存放视图对应的数据,这些数据仍存放在原来的基本表中。所以基本表中的数据发生变化,从视图中查询出的数据也就随之改变了。从这个意义上讲,视图就像一个窗口,透过它可以看到数据库中自己感兴趣的数据及其变化。视图一经定义,就可以和基本表一样被查询、被删除。也可以在一个视图之上再定义新的视图,但对视图的更新(增、删、改)操作则有一定得限制。

定义视图

一、建立视图

一般格式:

1
2
3
CREATE  VIEW <视图名> [(<列名> [,<列名>]…)] 
AS <子查询>
[WITH CHECK OPTION];

其中,子查询可以是任意复杂的SELECT语句,但通常不允许有order by子句和DISTINCT短语

with chech option 表示对视图进行update,insert和delete操作时要保证更新,插入,或删除的行满足视图定义中的谓词条件(即子查询中的条件表达式)。
组成视图的属性列名或者全部省略或全部指定,没有第三选择,如果省略了视图的各个属性列名,则隐含该视图由子查询中select子句目标列中的诸字段组成,但在下列三种情况下必须明确指定组成视图的所有列名:
(1)某个目标列不是单纯的属性名,而是聚集函数或列表达式
(2)多表连接时选出几个同名列作为视图的字段;
(3)需要在视图中为某个列启用新的更合适的名字。

例 建立信息系学生的视图

1
2
3
4
5
CREATE  VIEW IS_Student 
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS';

本例中省略了视图 IS_Student的列名,则用select子句目标列中的诸字段来组成属性列名,

RDBMS 执行 CREATE VIEW 语句的结果只是把视图的定义存入了数据字典,并不执行其中的select语句,只是在对视图查询时,才按视图的定义从基本表中将数据查出。

例 建立信息系学生的视图,并要求进行修改和插入操作时仍需保证该视图只有信息系的学生

1
2
3
4
5
6
CREATE  VIEW IS_Student 
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS'
WITH CHECK OPTION;

由于定义视图时加入了WITH CHECK OPTION子句,以后对该视图进行插入、修改和删除操作时,RDBMS会自动加上Sdept =‘IS’ 的条件

若一个视图是从单个基本表到处的,并且只是去掉基本表的某些行或者某些列,但保留了主码,我们称这类视图为行列子集视图,IS_Student就是一个行列子集视图。

视图不仅可以建立在单个基本表上,也可以建立在多个基本表上

例 建立信息系选修了1号课程的学生的视图

1
2
3
4
5
6
7
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,所以必须在视图后面明确说明视图的各个属性列名。

视图不仅可以建立在一个或多个基本表,还可以建立在一个或多个已定义好的视图,或建立在视图与视图上。
例: 建立信息系选修了1 号课程且成绩在90分以上的学生的视图

1
2
3
4
5
CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1
WHERE Grade>=90;

这个视图IS_S2就是定义在IS_S1之上的。

定义基本表时,为了减少数据库中的冗余数据,表中只存放基本数据,由基本数据经过各种计算派生出的数据一般是不存储的。

但由于视图中的数据并不实际存储,所以定义视图时可以根据应用的需要,设置一些派生属性列。

这些派生属性列由于在基本标中并不实际存在也称他们为 虚拟列,带虚拟列的视图也称为 带表达式的视图

例 定义一个反映学生出生年份的视图

1
2
3
4
CREATE  VIEW BT_S(Sno, Sname, Sbirth) /*BT_S带表达式的视图*/
AS
SELECT Sno, Sname, 2004-Sage
FROM Student;

视图中的出生年份是根据计算得到的

还可以用带有聚集函数和 GROUP BY子句的查询来定义视图,这种视图称为 分组视图

例 将学生的学号及他的平均成绩定义为一个视图

1
2
CREATE VIEW S_G(Sno, Gavg)
AS

由于AS子句中select语句的目标列平均成绩是通过作用聚集函数得到的,所以CREATE VIEW 中必须明确定义组成S_G视图的各个属性列名,S_G是一个分组视图

例 将Student表中所有女生记录定义为一个视图

1
2
3
4
5
CREATE VIEW  F_Student(stdnum, name, sex, age, dept)
AS
SELECT *
FROM Student
WHERE Ssex='女';

F_Student是由子查询 ‘select * ’建立起来的。F_Student视图的属性列与Student表的属性列一一对应。如果以后修改了基本表Student的结构,则Student表与F_Student视图的映像关系就被破坏了,该视图不能正常工作

为避免这种情况,最好修改基本表之后删除由该基本表导出的视图。然后重建这个视图。

二、删除视图

格式为:

1
DROP  VIEW <视图名> [CASCADE];
  • 该语句从数据字典中删除指定的视图定义
  • 如果该视图上还导出了其他视图,使用CASCADE级联删除语句,把该视图和由它导出的所有视图一起删除
  • 删除基表时,由该基表导出的所有视图定义都必须显式地使用DROP VIEW语句删除

例 删除视图BT_S:

1
DROP  VIEW BT_S;

删除视图IS_S1:

1
DROP  VIEW IS_S1;

其中IS_S1视图上还导出了IS_S2视图,所以该语句被拒绝执行,如果要删除,那么使用级联删除语句

1
DROP VIEW IS_S1 CASCADE /* 级联删除IS_S!和它到处的所有视图*/

查询视图

视图定义以后,就可以对基本表一样对视图进行查询了

例 信息系学生的视图中找出年龄小于20岁的学生

1
2
3
SELECT Sno, Sage
FROM IS_Student
WHERE Sage<20;

RDBMS 执行对视图查询时,首先进行有效性查询,检查查询中涉及的表、视图等是否存在,如果存在,则从数据字典中取出视图的定义,把定义中的子查询和用户的查询结合起来,转换成等价的对基本表的查询,然后再执行修正了的查询,这一转换过程称为视图消解。

取出S_Student视图的定义:

1
2
3
4
CREATE VIEW IS_Student
AS SELECT Sno, Sname, Sage
FROM Student
WHERE Sdept= 'IS';

本例转换后的查询语句:

1
2
3
SELECT Sno, Sage
FROM Student
WHERE Sdept='IS' AND Sage<20;

例 查询选修了 1号课程的信息系学生

1
2
3
SELECT IS_Student.Sno,Sname
FROM IS_Student.SC
WHERE IS_Student.Sno =SC.Sno AND SC.Cno='1';

本查询涉及视图IS_Student (虚表)和基本表SC ,通过这两个表的联结来完成用户请求。
在一般情况下,视图查询的转换是直接了当的,但有些情况下,这种转换不能直接进行,查询时会出现问题,如下面的例子

例 在上面S_G视图 中查询的平均成绩在90分以上的学生学号和平均成绩。
语句为:

1
2
3
SELECT * 
FROM S_C
WHERE Gavg >= 90;

其中S_G 视图的子查询为

1
2
3
SELECT Sno, AVG(Grade) 
FROM SC
GROUP BY Sno;

将本例中的查询语句与定义S_G视图的子查询结合,形成下列错误的查询语句:

1
2
3
4
SELECT Sno ,AVG(Grade)
FROM SC
WHERE AVG(Grade) >= 90
GROUP BY Sno;

因为where子句中是不能用聚集函数作为条件表达式,因此执行此修正后的查询将会出现语法错误,正确的转换的查询语句应该是:

1
2
3
4
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade) >= 90;

目前多数关系数据库系统对行列子集视图的查询均能进行正确转换,但对非行列子集视图的查询就不一定能做转换,这类查询应该直接对基本表进行。


更新视图

更新视图是指通过视图来插入(INSERT)、更新(UPDATE)和删除(DELETE)表中的数据。
因为视图是一个虚拟的表,其中没有数据。通过视图更新时,都是转换基本表来更新。
从用户角度看,更新视图与更新基本表相同;RDBMS将之转化为对基本表的更新操作。
为了防止用户通过视图对数据进行增加、删除、修改时,有意无意的对不属于视图范围内的基本表数据进行操作,可在定义视图时加上with check option子句,这样在视图上增删改数据时,RDBMS会检查视图定义的条件,若不满足条件,则拒绝该操作。
更新视图时,只能更新权限范围内的数据。超出了范围,就不能更新。

例 将信息系学生视图IS_Student中学号95002的学生姓名改为“刘辰”

1
2
3
UPDATE IS_Student
SET Sname='刘辰'
WHERE Sno='95002';

转换后的更新语句:

1
2
3
UPDATE Student
SET Sname='刘辰'
WHERE Sno='95002' AND Sdept = 'IS';

例 向信息系学生视图IS_Student中插入一个新的学生记录, 学号为95029,姓名为”赵新”, 年龄为20岁

1
2
3
INSERT
INTO IS_Student
VALUES('200215129','赵新' , 20'IS');

转换后对基本表的更新

1
2
3
INSERT
INTO Student (Sno, Sname ,Sage ,Sdept)
VALUES( '200215129' , '赵新' ,20 , 'IS');

这里系统自动将系名 ‘ IS ‘ 放入VALUES子句中,

例 删除信息系学生视图 IS_Student中学号为200215129的记录

1
2
3
DELETE
FROM IS_Student
WHERE Sno= '2OO215129'

转换为对基本表的更新:

1
2
3
DELETE 
FROM Student
WHERE Sno ='200215129' AND Sdept ='IS';

在关系数据库中,并不是所有的视图的都是可更新的,因为有些视图的更新不能唯一的有意义的转换成相应的基本表的更新

例如 视图S_G是由学号和平均成绩两个属性列组成的,其中平均成绩是由Student表中对元组分组后计算平均值得到的

1
2
3
4
5
CREATE VIEW S_G(Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;

但是修改平均成绩是错误的,错误的语句如下:

1
2
3
UPDATE S_G
SET Gvag = 90
WHERE Sno= '200215121';

这个对视图的更新是无法转换成对基本表SC的更新的,因为系统无法修改各科成绩,以使平均成绩为90,所以S_G视图是不可更新的

一般来说,行列子集视图是可更新的。目前各个关系数据库一般都只允许对行列子集进行更新,而且各个系统对视图的更新还有进一步的规定。


视图的作用

  1. 视图能够简化用户的操作
    视图机制使用户可以将注意力集中在所关心地数据上。如果这些数据不是直接来自基本表,则可以通过定义视图,使数据库看起来结构简单、清晰,并且可以简化用户的的数据查询操作。例如,那些定义了若干张表连接的视图,就将表与表之间的连接操作对用户隐藏起来了。换句话说,用户所作的只是对一个虚表的简单查询,而这个虚表是怎样得来的,用户无需了解。

  2. 视图使用户能以多种角度看待同一数据
    视图机制能使不同的用户以不同的方式看待同一数据,当许多不同种类的用户共享同一个数据库时,这种灵活性是非常必要的。

  3. 视图对重构数据库提供了一定程度的逻辑独立性
    数据的物理独立性是指用户的应用程序不依赖于数据库的物理结构。数据的逻辑独立性是指当数据库重构造时,如增加新的关系或对原有的关系增加新的字段,用户的应用程序不会受影响。层次数据库和网状数据库一般能较好地支持数据的物理独立性,而对于逻辑独立性则不能完全的支持。
    在关系数据库中,数据库的重构造往往是不可避免的。重构数据库最常见的是将一个基本表“垂直”地分成多个基本表。例如:将学生关系
    Student(Sno,Sname,Ssex,Sage,Sdept)
    分为SX(Sno,Sname,Sage)和SY(Sno,Ssex,Sdept)两个关系。这时原表Student为SX表和SY表自然连接的结果。如果建立一个视图Student:

    1
    2
    3
    4
    5
    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. 适当的利用视图可以更清晰地表达查询
    例如经常需要执行这样的查询“对每个学生找出他获得最高成绩的课程号”。可以先定义一个视图,求出每个同学获得的最高成绩:

    1
    2
    3
    4
    5
    CREATE VIEW VMGRADE
    AS
    SELECT Sno,MAX(Grade) Mgrade
    FROM SC
    GROUP BY Sno;

    然后用如下的查询语句完成查询:

    1
    2
    3
    SELECT SC.Sno,Cno 
    FROM SC,VMGRADE
    WHERE SC.Sno = VMGRADE.Sno AND SC.Grade = VMGRADE.Mgrade;
Just for fun!
------------- 文章已经到尾 -------------