第 3章 关系数据库标准语言 SQL
?3.1 SQL概述
?3.2 数据定义
?3.3 查询
?3.4 数据更新
?3.5 视图
?3.6 数据控制
?3.7 嵌入式 SQL
?3.8 小结
关系数据库标准语言 SQL(续 )
?SQL语言 (Structured Query Language)
– 1974年由 Boyce和 Chamberlin提出
– 1975年~ 1979年 IBM公司在 System R原型系
统上实现
– 是关系数据库的标准语言, 是数据库领域中
一个主流语言
关系数据库标准语言 SQL(续 )
? SQL标准
– SQL-86
? 第一个 SQL标准
? 由美国国家标准局 ( American National
Standard Institute,简称 ANSI) 公布
? 1987 年 国 际 标 准 化 组 织 ( International
Organization for Standardization,简称 ISO) 通

– SQL-89
– SQL-92
– SQL3
第 3章 关系数据库标准语言 SQL
?3.1 SQL概述
?3.2 数据定义
?3.3 查询
?3.4 数据更新
?3.5 视图
?3.6 数据控制
?3.7 嵌入式 SQL
?3.8 小结
3.1 SQL 概 述
? 3.1.1 SQL的特点
? 3.1.2 SQL语言的基本概念
3.1 SQL 概 述
? 3.1.1 SQL的特点
? 3.1.2 SQL语言的基本概念
3.1.1 SQL的特点
?⒈ 综合统一
? 2,高度非过程化
? 3,面向集合的操作方式
? 4,同一种语法结构提供两种使用方式
? 5,语言简捷,易学易用
⒈ 综合统一
? SQL语言集数据定义语言 DDL,数据操纵语
言 DML,数据控制语言 DCL的功能于一体
? 非关系模型的数据语言
– 模式数据定义语言 ( 模式 DDL)
– 外模式数据定义语言 ( 外模式 DDL或子模式 DDL)
– 与数据存储有关的描述语言 ( DSDL)
– 数据操纵语言 ( DML)
2,高度非过程化
?用户只需提出, 做什么,, 而不必指明
,怎么做,
?存取路径的选择以及 SQL语句的操作过
程由系统自动完成 。 大大减轻了用户负
担, 而且有利于提高数据独立性 。
3,面向集合的操作方式
?SQL语言采用集合操作方式
– 操作对象, 查找结果可以是元组的集合
– 一次插入, 删除, 更新操作的对象可以是
元组的集合
?非关系数据模型采用的是面向记录的操
作方式, 操作对象是一条记录 。
4,同一种语法结构提供两种使用方式
?自含式语言
– 能够独立地用于联机交互的使用方式
?嵌入式语言
– 能够嵌入到高级语言 ( 例如 C,COBOL,
FORTRAN,PL/1) 程序中, 供程序员设计
程序时使用 。
两种不同使用方式下,SQL语言的语法结构基
本一致
5,语言简捷,易学易用
表 3, 1 S Q L 语言的动词
S Q L 功 能 动 词
数 据 定 义 C R E A T E, D R O P, A L T E R
数 据 查 询 S E L E C T
数 据 操 纵 I N S E R T, U P D A T E
D E L E T E
数 据 控 制 G R A N T, R E V O K E
3.1 SQL 概 述
? 3.1.1 SQL的特点
? 3.1.2 SQL语言的基本概念
3.1.2 SQL语言的基本概念
S Q L 语言支持关系数据 库三级模 式结构
S Q L
视图 1 视图 2
基本表 1 基本表 2 基本表 4基本表 3
存储文件 1 存储文件 2
外模式
模 式
内模式
SQL语言的基本概念(续)
? 用户用 SQL语言对基本表和视图进行操作
? 基本表
– 本身独立存在的表, 一个关系对应一个表
– 一个 ( 或多个 ) 基本表对应一个存储文件
– 一个表可以带若干索引, 索引也存放在存储文件中
? 存储文件
– 存储文件的逻辑结构组成了关系数据库的内模式
– 存储文件的物理结构是任意的, 对用户是透明的
? 视图
– 从一个或几个基本表或视图导出的表
– 是虚表,只存放视图的定义而不存放对应数据
第 3章 关系数据库标准语言 SQL
?3.1 SQL概述
?3.2 数据定义
?3.3 查询
?3.4 数据更新
?3.5 视图
?3.6 数据控制
?3.7 嵌入式 SQL
?3.8 小结
数据定义概述
? SQL的数据定义功能
– 定义表 (模式 )
? 创建表
? 删除表
? 修改表定义
– 定义视图 (外模式 )
? 创建视图
? 删除视图
? 间接修改视图定义:删除 +创建
数据定义概述 (续 )
?SQL的数据定义功能 ( 续 )
– 定义索引 (内模式 )
? 创建索引
? 删除索引
? 间接修改索引定义:删除 +创建
数据定义概述 (续 )
表 3, 2 S Q L 的数据定义语句
操 作 方 式
操 作 对

创 建 删 除 修 改
表 C R E A T E
T A B L E
D R O P
T A B L E
A L T E R
T A B L E
视 图 C R E A T E
V I E W
D R O P V I E W
索 引 C R E A T E
I N D E X
D R O P
I N D E X
3.2 数 据 定 义
?3.2.1 定义、删除与修改基本表
?3.2.2 建立与删除索引
3.2 数 据 定 义
?3.2.1 定义、删除与修改基本表
?3.2.2 建立与删除索引
3.2.1 定义、删除与修改基本表
一, 定义基本表
二, 修改基本表
三、删除基本表
一、定义基本表
?关系名 ( 表名 )
?属性名 ( 列名 )
?完整性约束
定义基本表(续)
? 语句格式
CREATE TABLE <表名 >
( <列名 > <数据类型 >[ <列级完整性约束条件 > ]
[,<列名 > <数据类型 >[ <列级完整性约束条件 >] ]…
[,<表级完整性约束条件 > ] ) ;
– <表名 >:所要定义的基本表的名字
– <列名 >:组成该表的各个属性 ( 列 )
– <列级完整性约束条件 >:涉及相应属性列的完整性
约束条件
– <表级完整性约束条件 >:涉及一个或多个属性列的
完整性约束条件
定义基本表(续)
?表级完整性约束与列级完整性约束
?常用完整性约束
– 主码约束,PRIMARY KEY
– 参照完整性约束
– 唯一性约束,UNIQUE
– 非空值约束,NOT NULL
– 取值约束,CHECK
定义基本表(续)
?数据类型
– 不同的数据库系统支持的数据类型不完全相同
– IBM DB2 SQL支持的数据类型
? SMALLINT 半字长二进制整数 。
? INTEGER或 INT 全字长二进制整数 。
? DECIMAL(p[,q]) 压缩十进制数, 共 p位, 其中小数
或 DEC(p[,q]) 点后有 q位 。 0≤q≤p≤15,q=0
时可以省略不写 。
? FLOAT 双字长浮点数 。
定义基本表(续)
? 数据类型 ( 续 )
? CHARTER(n) 长度为 n的定长字符串 。
或 CHAR(n)
? VARCHAR(n) 最大长度为 n的变长字符串 。
? GRAPHIC(n) 长度为 n的定长图形字符串 。
? VARGRAPHIC(n) 最大长度为 n的变长图形字符串 。
? DATE 日期型, 格式为 YYYY-MM-DD。
? TIME 时间型, 格式为 HH.MM.SS。
? TIMESTAMP 日期加时间 。
定义基本表(续)
?数据类型 ( 续 )
– ORACLE SQL支持的数据类型
? VARCHAR2(n)
? CHAR(n)
? NUMBER[(p[,q])]
? DATE
? LONG
? RAW
或 LONGRAW
定义基本表(续)
?数据类型(续)
– KingBase ISQL支持的数据类型
? 字符串类型
CHARACTER[(长度 )] 最大长度为 256个字符
CHAR[(长度 )] CHARACTIC的同义词
CHARACTER VARYING(n)
VARCHAR(n)
TEXT 大文本
定义基本表(续)
?数据类型(续)
– KingBase ISQL支持的数据类型
? 精确数值类型
NUMERIC[(精度 [,标度 ])] 标度值应小于精度值
标度缺省为 0,精度缺省为 10
DECIMAL[(精度 [,标度 ])]
DEC[(精度 [,标度 ])] DECIMAL的同义词
INTEGER
INT INTEGER的同义词
SMALLINT
定义基本表(续)
?数据类型(续)
– KingBase ISQL支持的数据类型
? 近似数值类型
FLOAT[(精度 )] 可选精度浮点数
REAL 单精度浮点数
DOUBLE PRECISION 双精度浮点数
DOUBLE 同义词
定义基本表(续)
? 数据类型(续)
– KingBase ISQL支持的数据类型
? 日期时间类型
DATE 日期
TIME [WITH TIME ZONE] 时间
TIMETZ
TIME [WITHOUT TIME ZONE]
TIME
TIMESTAMP [WITH TIME ZONE] 日期和时间
TIMESTAMPTZ
TIMESTAMP [WITHOUT TIME ZONE]
TIMESTAMP
INTERVAL 通用的时间间隔
定义基本表(续)
? 数据类型(续)
– KingBase ISQL支持的数据类型
? 位串
BIT[(n)] 定长位串
BIT VARYING [(n)] 变长位串
BINARY LARGE OBJECT 二进制大对象
BLOB BINARY LARGE OBJECT的同义词
BYTEA 二进制位串
? 布尔型
BOOLEAN 逻辑布尔量
BOOL BOOLEAN的同义词
例题
[例 1] 建立一个, 学生, 表 Student,它由学号
Sno,姓名 Sname,性别 Ssex,年龄 Sage,所
在系 Sdept五个属性组成 。 其中学号不能为空,
值是唯一的, 并且姓名取值也唯一 。
Sno S n a m e S s e x S a g e S d e p t
  ↑      ↑       ↑       ↑      ↑
字 符 型   字 符 型   字 符 型   整数   字 符 型
长度为 5 长 度 为 20 长度为 1   长 度 为 15
不 能 为 空 值
例题(续)
CREATE TABLE Student
(Sno CHAR(5) NOT NULL UNIQUE,
Sname CHAR(20) UNIQUE,
Ssex CHAR(1),
Sage INT,
Sdept CHAR(15));
例题 (续)
[例 2] 建立一个, 学生选课, 表 SC,它由学号
Sno、课程号 Cno,修课成绩 Grade组成,其中
(Sno,Cno)为主码。
CREATE TABLE SC(
Sno CHAR(5),
Cno CHAR(3),
Grade int,
Primary key (Sno,Cno));
二、修改基本表
? 语句格式
ALTER TABLE <表名 >
[ ADD <新列名 > <数据类型 > [ 完整性约束 ] ]
[ DROP <完整性约束名 > ]
[ MODIFY <列名 > <数据类型 > ];
– <表名 >:要修改的基本表
– ADD子句,增加新列和新的完整性约束条件
– DROP子句,删除指定的完整性约束条件
– MODIFY子句,用于修改列名和数据类型
二、修改基本表
? 语句格式 ( 续 )
– 只能间接删除属性列
? 把表中要保留的列及其内容复制到一个新
表中
? 删除原表
? 再将新表重命名为原表名
– 不能修改完整性约束
– 不能为已有列增加完整性约束
例题
[例 2] 向 Student表增加, 入学时间, 列, 其数据
类型为日期型 。
ALTER TABLE Student ADD Scome DATE;
– 不论基本表中原来是否已有数据, 新增加的列一律
为空值 。
– 如果基本表中原来已有数据, 新增列不可有 NOT
NULL约束
例题
[例 3] 将年龄的数据类型改为半字长整数 。
ALTER TABLE Student MODIFY Sage SMALLINT;
– 注:修改原有的列定义有可能会破坏已有数据 。
例题
[例 4] 删除学生姓名必须取唯一值的约束 。
ALTER TABLE Student DROP UNIQUE(Sname);
三、删除基本表
?语句格式
DROP TABLE <表名 >;
– 系统从数据字典中删去,
? 该基本表的描述
? 该基本表上的所有索引的描述
– 系统从文件中删去表中的数据
– 表上的视图往往仍然保留, 但无法引用
例题
[例 5] 删除 Student表 。
DROP TABLE Student ;
3.2 数 据 定 义
?3.2.1 定义、删除与修改基本表
?3.2.2 建立与删除索引
3.2.2 建立与删除索引
? 建立索引是加快查询速度的有效手段
? 建立索引
– DBMS自动建立
? PRIMARY KEY
? UNIQUE
– DBA或表的属主 ( 即建立表的人 ) 根据需要建立
? 维护索引
– DBMS自动完成
? 使用索引
– DBMS自动选择是否使用索引以及使用哪些索引
一、建立索引
? 语句格式
CREATE [UNIQUE] [CLUSTER] INDEX <索引名 >
ON <表名 >(<列名 >[<次序 >][,<列名 >[<次序 >] ]…);
– 用 <表名 >指定要建索引的基本表名字
– 索引可以建立在该表的一 列 或多列上, 各列名之间用逗
号分隔
– 用 <次序 >指定索引值的排列次序, 升序,ASC,降序:
DESC。 缺省值,ASC
– UNIQUE表明此索引的每一个索引值只对应唯一的数据
记录
– CLUSTER表示要建立的索引是聚簇索引
建立索引 (续)
?唯一值索引
– 对于已含重复值的属性列不能建 UNIQUE索

– 对某个列建立 UNIQUE索引后, 插入新记录
时 DBMS会自动检查新记录在该列上是否取
了重复值 。 这相当于增加了一个 UNIQUE约
束 。
建立索引 (续)
?聚簇索引
– 建立聚簇索引后, 基表中数据也需要按指定
的聚簇属性值的升序或降序存放 。 也即聚簇
索引的索引项顺序与表中记录的物理顺序一
致 。
例,
CREATE CLUSTER INDEX Stusname ON Student(Sname);
在 Student表的 Sname( 姓名 ) 列上建立一个聚簇索引,
而且 Student表中的记录将按照 Sname值的升序存放
建立索引 (续)
– 在一个基本表上最多只能建立一个聚簇索引
– 聚簇索引的用途:对于某些类型的查询,可
以提高查询效率
– 聚簇索引的适用范围
? 很少对基表进行增删操作
? 很少对其中的变长列进行修改操作
例题
[例 6] 为学生 -课程数据库中的 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);
二、删除索引
?语句格式
DROP INDEX <索引名 >;
– 删除索引时,系统会从数据字典中删去有关
该索引的描述。
例题
[例 7] 删除 Student表的 Stusname索引 。
DROP INDEX Stusname;
第 3章 关系数据库标准语言 SQL
? 3.1 SQL概述
? 3.2 数据定义
? 3.3 查询
? 3.4 数据更新
? 3.5 视图
? 3.6 数据控制
? 3.7 嵌入式 SQL
? 3.8 小结
3.3 查 询
?3.3.1 单表查询
?3.3.2 连接查询
?3.3.3 嵌套查询
?3.3.4 集合查询
?3.3.5 小结
查询(续)
? 语句格式
SELECT [ALL|DISTINCT]
<目标列表达式 > [<别名 >]
[,<目标列表达式 >[<别名 >]] …
FROM <表名或视图名 >[<别名 >]
[,<表名或视图名 >[<别名 >] ] …
[ WHERE <条件表达式 > ]
[ GROUP BY <列名 > [,<列名 >] …
[ HAVING <条件表达式 > ] ]
[ ORDER BY <列名 > [,<列名 >] … [ ASC|DESC ] ];
语句格式
– SELECT子句,指定要显示的属性列
– FROM子句,指定查询对象 (基本表或视图 )
– WHERE子句,指定查询条件
– GROUP BY子句,对查询结果按指定列的值分组,
该属性列值相等的元组为一个组 。 通常会在每组中
作用集函数 。
– HAVING短语,筛选出满足指定条件的组
– ORDER BY子句,对查询结果表按指定列值的升序
或降序排序
示例数据库
学生 -课程数据库
? 学生表,
Student(Sno,Sname,Ssex,Sage,Sdept)
? 课程表,
Course(Cno,Cname,Cpno,Ccredit)
? 学生选课表,
SC(Sno,Cno,Grade)
3.3 查 询
?3.3.1 单表查询
?3.3.2 连接查询
?3.3.3 嵌套查询
?3.3.4 集合查询
?3.3.5 小结
3.3.1 单表查询
?单表查询
查询仅涉及一个表, 是一种最简单的查询操作
– 选择表中的若干列
– 选择表中的若干元组
– 对查询结果排序
– 使用集函数
– 对查询结果分组
一、选择表中的若干列
?属投影运算
– 不消除重复行
?变化方式主要表现在 SELECT子句的 <目
标表达式 >上
– 查询指定列
– 查询全部列
– 查询经过计算的值
1,查询指定列
?方法
– 在 SELECT子句的 <目标列表达式 >中指定
要查询的属性
– <目标列表达式 >中各个列的先后顺序可以
与表中的逻辑顺序不一致 。 即用户可以根据
应用的需要改变列的显示顺序
例题
[例 1] 查询全体学生的学号与姓名 。
SELECT Sno,Sname
FROM Student;
[例 2] 查询全体学生的姓名, 学号, 所在系 。
SELECT Sname,Sno,Sdept
FROM Student;
2,查询全部列
?方法
– 在 SELECT关键字后面列出所有列名
– 当列的显示顺序与其在基表中的顺序相同时,
也可以简单地将 <目标列表达式 >指定为 *
例题
[例 3] 查询全体学生的详细记录 。
SELECT Sno,Sname,Ssex,Sage,Sdept
FROM Student;

SELECT *
FROM Student;
3,查询经过计算的值
?方法
– SELECT子句的 <目标列表达式 >为表达式
? 算术表达式
? 字符串常量
? 函数
? 列别名
? 等
例题
[例 4] 查全体学生的姓名及其出生年份 。
SELECT Sname,2003-Sage
FROM Student;
输出结果,
Sname 2003-Sage
--------- -------------
李勇 1976
刘晨 1977
王名 1978
张立 1978
例题(续)
[例 5] 查询全体学生的姓名, 出生年份和
所有系, 要求用小写字母表示所有系名 。
SELECT Sname,'Year of Birth,',2002-Sage,
ISLOWER(Sdept)
FROM Student;
例题(续)
输出结果,
Sname 'Year of Birth:' 2002-Sage ISLOWER(Sdept)
------- ---------------- --------- --------------
李勇 Year of Birth,1976 cs
刘晨 Year of Birth,1977 if
王名 Year of Birth,1978 ma
张立 Year of Birth,1978 if
例题(续)
[例 5.1] 使用列别名改变查询结果的列标题
SELECT Sname NAME,'Year of Birth,' BIRTH,
2002-Sage BIRTHDAY,
ISLOWER(Sdept) DEPARTMENT
FROM Student;
输出结果,
NAME BIRTH BIRTHDAY DEPARTMENT ------- ---------------- ------------- ------------------
李勇 Year of Birth,1976 cs
刘晨 Year of Birth,1977 if
王名 Year of Birth,1978 ma
张立 Year of Birth,1978 if
二、选择表中的若干元组
?消除取值重复的行
?查询满足条件的元组
1,消除取值重复的行
?方法
– 在 SELECT子句中使用 DISTINCT短语
例题
假设 SC表中有下列数据
Sno Cno Grade
------- ------- -------
95001 1 92
95001 2 85
95001 3 88
95002 2 90
95002 3 80
例题(续)
[例 6] 查询选修了课程的学生学号 。
(1) SELECT Sno
FROM SC;

SELECT ALL Sno
FROM SC;
结果,Sno
-------
95001
95001
95001
95002
95002
例题(续)
(2)
SELECT DISTINCT Sno
FROM SC;
结果,
Sno
-------
95001
95002
例题(续)
? 注意
DISTINCT短语的作用范围是所有目标列
例:查询选修课程的各种成绩
错误的写法
SELECT DISTINCT Cno,DISTINCT Grade
FROM SC;
正确的写法
SELECT DISTINCT Cno,Grade
FROM SC;
2,查询满足条件的元组
? 属选择运算
? 通过 WHERE子句实现
– 比较大小
– 确定范围
– 确定集合
– 字符串匹配
– 涉及空值的查询
– 多重条件查询
查询满足条件的元组 (续)
表 3, 3 常 用 的 查 询 条 件
查 询 条 件 谓 词
比 较
=, >, <, >=, <=, !=, <>, !>, !< ;
N O T + 上述比较运算符
确定范围 B E T W E E N A N D, N O T B E T W E E N A N D
确定集合 IN, N O T I N
字符匹配 L I K E, N O T L I K E
空 值 I S N U L L, I S N O T N U L L
多重条件 AND, OR
WHERE子句常用的查询条件
(1) 比较大小
?方法
– 在 WHERE子句的 <比较条件 >中使用比较运
算符
? =,>,<,>=,<=,!=或 <>,!>,!<,
? 逻辑运算符 NOT + 含上述比较运算符的表达式
例题
[例 7] 查询计算机系全体学生的名单 。
SELECT Sname
FROM Student
WHERE Sdept = 'CS';
例题
[例 8] 查询所有年龄在 20岁以下的学生姓名及其年龄 。
SELECT Sname,Sage
FROM Student
WHERE Sage < 20;

SELECT Sname,Sage
FROM Student
WHERE NOT Sage >= 20;
例题(续)
[例 9] 查询考试成绩有不及格的学生的学号 。
SELECT DISTINCT Sno
FROM SC
WHERE Grade < 60;
(2) 确定范围
?方法
– 使用谓词 BETWEEN … AND …
NOT BETWEEN … AND …
? BETWEEN后:范围的下限 ( 即低值 )
? AND后:范围的上限 ( 即高值 )
– 用多重条件查询实现
例题
[例 10] 查询年龄在 20~23岁 ( 包括 20岁和 23岁 )
之间的学生的姓名, 系别和年龄 。
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
例题(续)
[例 11] 查询年龄不在 20~23岁之间的学生姓名,
系别和年龄 。
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage NOT BETWEEN 20 AND 23;
(3) 确定集合
?方法
– 使用谓词 IN <值表 >
NOT IN <值表 >
? <值表 >:用逗号分隔的一组取值
– 用多重条件查询实现
例题
[例 12] 查询信息系 ( IS), 数学系 ( MA) 和计
算机科学系 ( CS) 学生的姓名和性别 。
SELECT Sname,Ssex
FROM Student
WHERE Sdept IN ( 'IS','MA','CS' );
例题
[例 13] 查询既不是信息系, 数学系, 也不是计算
机科学系的学生的姓名和性别 。
SELECT Sname,Ssex
FROM Student
WHERE Sdept NOT IN ( 'IS','MA','CS' );
(4) 字符串匹配
? 方法
–使用谓词 LIKE或 NOT LIKE
[NOT] LIKE ?<匹配串 >? [ESCAPE ? <换码字符 >?]
–<匹配串 >:指定匹配模板
? 匹配模板:固定字符串或含通配符的字符串
? 当匹配模板为固定字符串时, 可以用 =运算符取代 LIKE谓
词, 用 != 或 < >运算符取代 NOT LIKE谓词
字符串匹配 (续 )
例题:匹配模板为固定字符串
[例 14] 查询学号为 95001的学生的详细情况 。
SELECT *
FROM Student
WHERE Sno LIKE '95001';
等价于,
SELECT *
FROM Student
WHERE Sno = '95001';
字符串匹配 (续 )
?通配符
?% (百分号 ) 代表任意长度(长度可以为 0)的
字符串。
– 例,a%b表示以 a开头,以 b结尾的任意长度
的字符串。如 acb,addgb,ab 等都满足该匹
配串。
?_ (下横线 ) 代表任意单个字符。
– 例,a_b表示以 a开头,以 b结尾的长度为 3的
任意字符串。如 acb,afb等都满足该匹配串。
字符串匹配 (续 )
例题, 匹配模板为含通配符的字符串
[例 15] 查询所有姓刘学生的姓名、学号和性别。
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname LIKE ? 刘 %? ;
字符串匹配 (续 )
匹配模板为含通配符的字符串(续)
[例 16] 查询姓 "欧阳 "且全名为三个汉字的学生
的姓名。
SELECT Sname
FROM Student
WHERE Sname LIKE ? 欧阳 _ _';
字符串匹配 (续 )
匹配模板为含通配符的字符串(续)
[例 17] 查询名字中第 2个字为 "阳 "字的学生的姓
名和学号。
SELECT Sname,Sno
FROM Student
WHERE Sname LIKE '_ _阳 %';
字符串匹配 (续 )
匹配模板为含通配符的字符串(续)
[例 18] 查询所有不姓刘的学生姓名。
SELECT Sname,Sno,Ssex
FROM Student
WHERE Sname NOT LIKE '刘 %';
字符串匹配 (续 )
– ESCAPE 短语,
? 当用户要查询的字符串本身就含有 % 或
_ 时,要使用 ESCAPE '<换码字符 >' 短语
对通配符进行转义。
字符串匹配 (续 )
例题,使用换码字符将通配符转义为普通
字符
[例 19] 查询 DB_Design课程的课程号和学分。
SELECT Cno,Ccredit
FROM Course
WHERE Cname LIKE 'DB_Design'
字符串匹配 (续 )
使用换码字符将通配符转义为普通字符 (续 )
[例 19] (续 )
SELECT Cno,Ccredit
FROM Course
WHERE Cname LIKE 'DB\_Design'
ESCAPE '\'
字符串匹配 (续 )
使用换码字符将通配符转义为普通字符 (续 )
[例 20] 查询以 "DB_"开头,且倒数第 3个字符为 i
的课程的详细情况。
SELECT *
FROM Course
WHERE Cname LIKE 'DB\_%i_ _' ESCAPE ' \ ';
(5) 涉及空值的查询
? 方法
– 使用谓词 IS NULL或 IS NOT NULL
–,IS NULL” 不能用,= NULL” 代替
例题
[例 21] 某些学生选修课程后没有参加考试,
所以有选课记录,但没有考试成绩。查询缺
少成绩的学生的学号和相应的课程号。
SELECT Sno,Cno
FROM SC
WHERE Grade IS NULL;
例题 (续 )
[例 22] 查所有有成绩的学生学号和课程号。
SELECT Sno,Cno
FROM SC
WHERE Grade IS NOT NULL;
(6) 多重条件查询
? 方法
– 用逻辑运算符 AND和 OR来联结多个查询条

? AND的优先级高于 OR
? 可以用括号改变优先级
– 可用来实现多种其他谓词
? [NOT] IN
? [NOT] BETWEEN … AND …
例题
[例 23] 查询计算机系年龄在 20岁以下的学生姓名。
SELECT Sname
FROM Student
WHERE Sdept= 'CS' AND Sage<20;
例题(续)
改写 [例 12]
[例 12] 查询信息系( IS)、数学系( MA)和计算机科学系
( CS)学生的姓名和性别。
SELECT Sname,Ssex
FROM Student
WHERE Sdept IN ( 'IS','MA','CS' )
可改写为,
SELECT Sname,Ssex
FROM Student
WHERE Sdept= ' IS ' OR Sdept= ' MA' OR Sdept= ' CS ';
例题(续)
改写 [例 10]
[例 10] 查询年龄在 20~23岁(包括 20岁和 23岁)
之间的学生的姓名、系别和年龄 。
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage BETWEEN 20 AND 23;
可改写为,
SELECT Sname,Sdept,Sage
FROM Student
WHERE Sage>=20 AND Sage<=23;
三、对查询结果排序
● 方法
– 使用 ORDER BY子句
? 可以按一个或多个属性列排序
? 升序,ASC;降序,DESC;缺省值为升序
– 当排序列含空值时
? ASC:排序列为空值的元组最后显示
? DESC:排序列为空值的元组最先显示
对查询结果排序(续)
?例题
[例 24] 查询选修了 3号课程的学生的学号及其
成绩, 查询结果按分数降序排列 。
SELECT Sno,Grade
FROM SC
WHERE Cno= ' 3 '
ORDER BY Grade DESC;
对查询结果排序(续)
结果
Sno Grade
------- -------
95010
95024
95007 92
95003 82
95010 82
95009 75
95014 61
95002 55
对查询结果排序(续)
[例 25] 查询全体学生情况, 查询结果按所
在系的系号升序排列, 同一系中的学生
按年龄降序排列 。
SELECT *
FROM Student
ORDER BY Sdept,Sage DESC;
四、使用集函数
? 方法
– 5类主要集函数
? 计数
COUNT( [DISTINCT|ALL] *)
COUNT( [DISTINCT|ALL] <列名 >)
? 计算总和
SUM( [DISTINCT|ALL] <列名 >)
? 计算平均值
AVG( [DISTINCT|ALL] <列名 >)
使用集函数(续)
– 5类主要集函数 (续 )
? 求最大值
MAX( [DISTINCT|ALL] <列名 >)
? 求最小值
MIN( [DISTINCT|ALL] <列名 >)
– DISTINCT短语:在计算时要取消指定列中
的重复值
– ALL短语:不取消重复值
– ALL为缺省值
使用集函数 (续)
?例题
[例 26] 查询学生总人数 。
SELECT COUNT(*)
FROM Student;
[例 27] 查询选修了课程的学生人数 。
SELECT COUNT(DISTINCT Sno)
FROM SC;
注:用 DISTINCT以避免重复计算学生人数
使用集函数 (续)
[例 28] 计算 1号课程的学生平均成绩 。
SELECT AVG(Grade)
FROM SC
WHERE Cno= ' 1 ';
[例 29] 查询选修 1号课程的学生最高分数 。
SELECT MAX(Grade)
FROM SC
WHER Cno= ' 1 ';
五、对查询结果分组
?用途
– 细化集函数的作用对象
? 未对查询结果分组, 集函数将作用于整个查询
结果
? 对查询结果分组后,集函数将分别作用于每个

对查询结果分组 (续)
? 方法 ( 参照后面例题 )
– 使用 GROUP BY子句分组
? 分组方法:按指定的一列或多列值分组, 值相等
的为一组
? 使用 GROUP BY子句后, SELECT子句的列名
列表中只能出现分组属性和集函数
? GROUP BY子句的作用对象是查询的中间结果

例题
[例 30] 求各个课程号及相应的选课人数 。
SELECT Cno,COUNT(Sno)
FROM SC
GROUP BY Cno;
结果
Cno COUNT(Sno)
1 22
2 34
3 44
4 33
5 48
例题
[例 31] 求各个课程号及相应的课程成绩在 90分以上的学生
人数 。
SELECT Cno,COUNT(Sno)
FROM SC
WHERE Grade>=90
GROUP BY Cno;
结果
Cno COUNT(Sno)
1 13
2 7
4 3
5 8
对查询结果分组 (续)
? 方法 (续 )
– 使用 HAVING短语筛选最终输出结果
? 只有满足 HAVING短语指定条件的组才输出
? HAVING短语与 WHERE子句的区别:作用对象
不同
– WHERE子句作用于基表或视图, 从中选择
满足条件的元组 。
– HAVING短语作用于组, 从中选择满足条件
的组 。
例题
[例 32] 查询选修了 3门以上课程的学生学号 。
SELECT Sno
FROM SC
GROUP BY Sno
HAVING COUNT(*) >3;
例题
[例 33] 查询有 3门以上课程在 90分以上的学生的
学号及 90分以上的课程数 。
SELECT Sno,COUNT(*)
FROM SC
WHERE Grade>=90
GROUP BY Sno
HAVING COUNT(*)>=3;
3.3 查 询
?3.3.1 单表查询
?3.3.2 连接查询
?3.3.3 嵌套查询
?3.3.4 集合查询
?3.3.5 小结
3.3.2 连接查询
概述
? 同时涉及多个表的查询称为连接查询
? 连接条件
– 用来连接两个表的条件称为连接条件或连接谓词
– 常用格式
? [<表名 1>.]<列名 1> <比较运算符 > [<表名 2>.]<列名 2>
比较运算符,=,>,<,>=,<=,!=
? [<表名 1>.]<列名 1> BETWEEN [<表名 2>.]<列名 2> AND
[<表名 2>.]<列名 3>
连接查询 (续)
? 连接字段
– 连接谓词中的列名称为连接字段
– 连接条件中的各连接字段类型必须是可比的,
但不必是相同的
连接查询 (续)
?连接操作的执行过程
– 嵌套循环法 (NESTED-LOOP)
? 首先在表 1中找到第一个元组, 然后从头开始扫
描表 2,逐一查找满足连接件的元组, 找到后就
将表 1中的第一个元组与该元组拼接起来, 形成
结果表中一个元组 。
? 表 2全部查找完后, 再找表 1中第二个元组, 然后
再从头开始扫描表 2,逐一查找满足连接条件的
元组, 找到后就将表 1中的第二个元组与该元组
拼接起来, 形成结果表中一个元组 。
? 重复上述操作, 直到表 1中的全部元组都处理完
毕为止 。
连接查询 (续)
– 排序合并法 (SORT-MERGE):常用于 =连接
? 首先按连接属性对表 1和表 2排序
? 对表 1的第一个元组, 从头开始扫描表 2,
顺序查找满足连接条件的元组, 找到后就
将表 1中的第一个元组与该元组拼接起来,
形成结果表中一个元组 。 当遇到表 2中第
一条大于表 1连接字段值的元组时, 对表 2
的查询不再继续
连接查询 (续)
– 排序合并法 (续 )
? 找到表 1的第二条元组, 然后从刚才的中
断点处继续顺序扫描表 2,查找满足连接
条件的元组, 找到后就将表 1中的第一个
元组与该元组拼接起来, 形成结果表中一
个元组 。 直接遇到表 2中大于表 1连接字段
值的元组时, 对表 2的查询不再继续
? 重复上述操作, 直到表 1或表 2中的全部元
组都处理完毕为止
连接查询 (续)
– 索引连接 (INDEX-JOIN)
? 对表 2按连接字段建立索引
? 对表 1中的每个元组, 依次根据其连接字
段值查询表 2的索引, 从中找到满足条件
的元组, 找到后就将表 1中的第一个元组
与该元组拼接起来, 形成结果表中一个元

连接查询 (续)
? SQL中连接查询的主要类型
– 广义笛卡尔积
– 等值连接 (含自然连接 )
– 非等值连接查询
– 自身连接查询
– 外连接查询
– 复合条件连接查询
连接查询 (续)
一, 广义笛卡尔积
二, 等值与非等值连接查询
三, 自身连接查询
四, 外连接查询
五, 复合条件连接查询
一、广义笛卡尔积
?不带连接谓词的连接
? 很少使用
例,
SELECT Student.*,SC.*
FROM Student,SC
二、等值与非等值连接查询
?等值连接
?自然连接
?非等值连接
二、等值与非等值连接查询
?等值连接
– 连接运算符为 = 的连接操作
? [<表名 1>.]<列名 1> = [<表名 2>.]<列名 2>
– 任何子句中引用表 1和表 2中同名属性时,
都必须加表名前缀 。 引用唯一属性名时可
以加也可以省略表名前缀 。
等值与非等值连接查询(续)
[例 32] 查询每个学生及其选修课程的情况 。
SELECT Student.*,SC.*
FROM Student,SC
WHERE Student.Sno=SC.Sno;
等值与非等值连接查询(续)
结果
假设 Student表, SC表分别有下列数据,
Student表
Sno
Sname
Ssex
Sage
Sdept
95001
李勇

20
CS
95002
刘晨

19
IS
95003
王敏

18
MA
95004
张立

19
IS
等值与非等值连接查询(续)
SC表
Sno
Cno
Grade
95001
1
92
95001
2
85
95001
95002
95002
3
2
3
88
90
80
等值与非等值连接查询(续)
结果表
Student.Sno Sname Ssex Sage Sdept SC.Sno Cno Grade
95001 李勇 男 20 CS 95001 1 92
95001 李勇 男 20 CS 95001 2 85
95001 李勇 男 20 CS 95001 3 88
95002 刘晨 女 19 IS 95002 2 90
95002 刘晨 女 19 IS 95002 3 80
等值与非等值连接查询(续)
? 自然连接
– 等值连接的一种特殊情况, 把目标列中重复的属性
列去掉 。
? <表名 1>.<列名 1> = <表名 2>.<列名 2>
– SELECT语句不能直接实现自然连接
[例 33] 对 [例 32]用自然连接完成 。
SELECT Student.Sno, Sname, Ssex, Sage,
Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno=SC.Sno;
等值与非等值连接查询(续)
?非等值连接
– 连接运算符不为 = 的连接操作
[<表名 1>.]<列名 1> <比较运算符 > [<表名 2>.]<列名 2>
比较运算符,>,<,>=,<=,!=
[<表名 1>.]<列名 1> BETWEEN [<表名 2>.]<列名 2>
AND [<表名 2>.]<列名 3>
三、自身连接
?一个表与其自己进行连接,称为表的 自
身连接
?表示方法
– 需要给表起别名以示区别
– 由于所有属性名都是同名属性,因此必须使
用别名前缀
自身连接(续)
[例 34] 查询每一门课的间接先修课 ( 即先
修课的先修课 ) 。
SELECT FIRST.Cno,SECOND.Cpno
FROM Course FIRST,Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
自身连接(续)
结果
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
自身连接(续)
查询结果
1 7
3 5
5 6
cno cpno
四、外连接( Outer Join)
?外连接与普通连接的区别
– 普通连接操作只输出满足连接条件的元组
– 外连接操作以指定表为连接主体,将主体表
中不满足连接条件的元组一并输出
外连接(续)
?外连接操作
– 在表名后面加外连接操作符 (*)或 (+)指定非
主体表
– 非主体表有一, 万能, 的虚行, 该行全部由
空值组成
– 虚行可以和主体表中所有不满足连接条件的
元组进行连接
– 由于虚行各列全部是空值, 因此与虚行连接
的结果中, 来自非主体表的属性值全部是空

外连接(续)
?外连接操作的种类
– 左外连接
? 外连接符出现在连接条件的左边
– 右外连接
? 外连接符出现在连接条件的右边
外连接(续)
例:用外连接操作改写 [例 33]
SELECT Student.Sno,Sname,Ssex,
Sage,Sdept,Cno,Grade
FROM Student,SC
WHERE Student.Sno = SC.Sno(*);
外连接(续)
结果,
Student.Sno Sname Ssex Sage Sdept Cno Grade
95001 李勇 男 20 CS 1 92
95001 李勇 男 20 CS 2 85
95001 李勇 男 20 CS 3 88
95002 刘晨 女 19 IS 2 90
95002 刘晨 女 19 IS 3 80
95003 王敏 女 18 MA
95004 张立 男 19 IS
五、复合条件连接
?WHERE子句中含多个连接条件时, 称
为复合条件连接
?复合条件连接的类型
– 两表按多个属性连接
– 自身按多个属性连接
– 多表连接
复合条件连接(续)
[例 35] 假设学校中性别相同的学生不会重名 。 现如下设
计学生表和选修表,
Std(Sname,Ssex,Sage,Sdept)
StdC(Sname,Ssex,Cno,Grade)
查询选修 2号课程且成绩在 90分以上的所有学生的姓名,
性别及所在系 。
SELECT Std.Sname,Std.Ssex,Sdept
FROM Std,StdC
WHERE Std.Sname = StdC.Sname /* 连接谓词 */
AND Std.Ssex = StdC.Ssex /* 连接谓词 */
AND StdC.Cno= ' 2 ‘ /* 其他限定条件 */
AND StdC.Grade>90; /* 其他限定条件 */
复合条件连接(续)
[例 36] 查询每个学生的学号, 姓名, 选修的课程名及成
绩 。
SELECT Student.Sno,Sname,Cname,Grade
FROM Student,SC,Course
WHERE Student.Sno = SC.Sno
and SC.Cno = Course.Cno;
结果,
Student.Sno Sname Cname Grade
95001 李勇 数据库 92
95001 李勇 数学 85
95001 李勇 信息系统 88
95002 刘晨 数学 90
95002 刘晨 信息系统 80
3.3 查 询
?3.3.1 单表查询
?3.3.2 连接查询
?3.3.3 嵌套查询
?3.3.4 集合查询
?3.3.5 小结
3.3.3 嵌套查询
?嵌套查询概述
?嵌套查询分类
?嵌套查询求解方法
?引出子查询的谓词
嵌套查询 (续 )
?嵌套查询概述
– 一个 SELECT-FROM-WHERE语句称为一
个查询块
– 将一个查询块嵌套在另一个查询块的
WHERE子句或 HAVING短语的条件中的查
询称为嵌套查询
嵌套查询 (续 )

SELECT Sname 外层查询 /父查询
FROM Student
WHERE Sno IN
( SELECT Sno子 内层查询 /子查询
FROM SC
WHERE Cno= ' 2 ');
嵌套查询 (续 )
– 子查询的限制
? 不能使用 ORDER BY子句
– 层层嵌套方式反映了 SQL语言的结构化
– 有些嵌套查询可以用连接运算替代
嵌套查询 (续 )
?嵌套查询分类
– 不相关子查询
? 子查询的查询条件不依赖于父查询
– 相关子查询
? 子查询的查询条件依赖于父查询
嵌套查询 (续 )
?嵌套查询求解方法
– 不相关子查询
? 是由里向外逐层处理。即每个子查询在上
一级查询处理之前求解,子查询的结果用
于建立其父查询的查找条件。
嵌套查询 (续 )
?嵌套查询求解方法(续)
– 相关子查询
? 首先取外层查询中表的第一个元组,根据
它与内层查询相关的属性值处理内层查询,
若 WHERE子句返回值为真,则取此元组
放入结果表;
? 然后再取外层表的下一个元组;
? 重复这一过程,直至外层表全部检查完为
止。
嵌套查询 (续 )
?引出子查询的谓词
– 带有 IN谓词的子查询
– 带有比较运算符的子查询
– 带有 ANY或 ALL谓词的子查询
– 带有 EXISTS谓词的子查询
一、带有 IN谓词的子查询
[例 37] 查询与“刘晨”在同一个系学习的学生。
– 此查询要求可以分步来完成
① 确定“刘晨”所在系名
SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ';
结果为,
Sdept
IS
带有 IN谓词的子查询(续)
② 查找所有在 IS系学习的学生。
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept= ' IS ';
结果为,
Sno Sname Sdept
95001 刘晨 IS
95004 张立 IS
带有 IN谓词的子查询(续)
– 构造嵌套查询
将第一步查询嵌入到第二步查询的条件中
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept IN
(SELECT Sdept
FROM Student
WHERE Sname= ? 刘晨 ’ );
此查询为不相关子查询。 DBMS求解该查询时也
是分步去做的。
带有 IN谓词的子查询(续)
– 用自身连接完成本查询要求
SELECT Sno,Sname,Sdept
FROM Student S1,Student S2
WHERE S1.Sdept = S2.Sdept AND
S2.Sname = '刘晨 ';
带有 IN谓词的子查询(续)
– 父查询和子查询中的表均可以定义别名
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE S1.Sdept IN
(SELECT Sdept
FROM Student S2
WHERE S2.Sname= ? 刘晨 ’ );
带有 IN谓词的子查询(续)
[例 38]查询选修了课程名为“信息系统”的学生学号和姓

– 嵌套查询
SELECT Sno,Sname ③ 最后在 Student关系中
FROM Student 取出 Sno和 Sname
WHERE Sno IN
(SELECT Sno ② 然后在 SC关系中找出选
FROM SC 修了 3号课程的学生学号
WHERE Cno IN
(SELECT Cno ① 首先在 Course关系中找出
“信
FROM Course 息系统”的课程号,结果为 3

WHERE Cname= ? 信息系统’ ));
带有 IN谓词的子查询(续)
结果,
Sno Sname
---- -----
95001 李勇
95002 刘晨
带有 IN谓词的子查询(续)
– 连接查询
SELECT Sno,Sname
FROM Student,SC,Course
WHERE Student.Sno = SC.Sno AND
SC.Cno = Course.Cno AND
Course.Cname=?信息系统’;
二、带有比较运算符的子查询
● 使用范围
– 当能确切知道内层查询返回单值时,可用比
较运算符( >,<,=,>=,<=,!=或 < >)。
– 与 ANY或 ALL谓词配合使用
带有比较运算符的子查询(续)
例:假设一个学生只可能在一个系学习,并且必
须属于一个系,则在 [例 37]可以用 = 代替 IN,
SELECT Sno,Sname,Sdept
FROM Student
WHERE Sdept =
SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ';
带有比较运算符的子查询(续)
● 子查询一定要跟在比较符之后
错误的例子,
SELECT Sno,Sname,Sdept
FROM Student
WHERE ( SELECT Sdept
FROM Student
WHERE Sname= ' 刘晨 ' ) = Sdept;
三、带有 ANY或 ALL谓词的子查询
● 谓词语义
– ANY:任意一个值
– ALL:所有值
带有 ANY或 ALL谓词的子查询(续)
● 需要配合使用比较运算符
> ANY 大于子查询结果中的某个值
> ALL 大于子查询结果中的所有值
< ANY 小于子查询结果中的某个值
< ALL 小于子查询结果中的所有值
>= ANY 大于等于子查询结果中的某个值
>= ALL 大于等于子查询结果中的所有值
<= ANY 小于等于子查询结果中的某个值
<= ALL 小于等于子查询结果中的所有值
= ANY 等于子查询结果中的某个值
=ALL 等于子查询结果中的所有值(通常没有实际意义)
!=(或 <>) ANY 不等于子查询结果中的某个值
!=(或 <>) ALL 不等于子查询结果中的任何一个值
带有 ANY或 ALL谓词的子查询(续)
[例 39] 查询其他系中比信息系某一学生年龄小的
学生姓名和年龄
SELECT Sname,Sage
FROM Student
WHERE Sage < ANY (SELECT Sage
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <> ' IS ' ;
/* 注意这是父查询块中的条件 */
带有 ANY或 ALL谓词的子查询(续)
结果
Sname Sage
王敏 18
执行过程
DBMS执行此查询时,首先处理子查询,找
出 IS系中所有学生的年龄,构成一个集合 (19,
18)。然后处理父查询,找所有不是 IS系且年
龄小于 19或 18的学生。
带有 ANY或 ALL谓词的子查询(续)
● ANY和 ALL谓词有时可以用集函数实现
– ANY与 ALL与集函数的对应关系
= <>或 != < <= > >=
ANY IN -- <MAX <=MAX >MIN >= MIN
ALL -- NOT IN <MIN <= MIN >MAX >= MAX
带有 ANY或 ALL谓词的子查询(续)
– 用集函数实现子查询通常比直接用 ANY或
ALL查询效率要高,因为前者通常能够减
少比较次数
带有 ANY或 ALL谓词的子查询(续)
[例 39']:用集函数实现 [例 39]
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MAX(Sage)
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <> ' IS ?;
带有 ANY或 ALL谓词的子查询(续)
[例 40] 查询其他系中比信息系所有学生年龄都小
的学生姓名及年龄。
方法一:用 ALL谓词
SELECT Sname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <> ' IS ?;
查询结果为空表。
带有 ANY或 ALL谓词的子查询(续)
方法二:用集函数
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept= ' IS ')
AND Sdept <>' IS ?;
四、带有 EXISTS谓词的子查询
● 1,EXISTS谓词
● 2,NOT EXISTS谓词
● 3,不同形式的查询间的替换
● 4,相关子查询的效率
● 5,用 EXISTS/NOT EXISTS实现全称量词
● 6,用 EXISTS/NOT EXISTS实现逻辑蕴函
带有 EXISTS谓词的子查询 (续 )
● 1,EXISTS谓词
– 存在量词 ?
– 带有 EXISTS谓词的子查询不返回任何数据,
只产生逻辑真值, true”或逻辑假值
,false”。
● 若内层查询结果非空,则返回真值
● 若内层查询结果为空,则返回假值
– 由 EXISTS引出的子查询,其目标列表达式
通常都用 *,因为带 EXISTS的子查询只返回
真值或假值,给出列名无实际意义
● 2,NOT EXISTS谓词
带有 EXISTS谓词的子查询 (续 )
思路分析,
● 本查询涉及 Student和 SC关系。
● 在 Student中依次取每个元组的 Sno值,用此值去
检查 SC关系。
● 若 SC中存在这样的元组,其 Sno值等于此
Student.Sno值,并且其 Cno= '1',则取此
Student.Sname送入结果关系。
带有 EXISTS谓词的子查询 (续 )
[例 41] 查询所有选修了 1号课程的学生姓名。
– 用嵌套查询
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno AND
Cno= ' 1 ');
求解过程
带有 EXISTS谓词的子查询 (续 )
– 用连接运算
SELECT Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno AND
SC.Cno= '1';
带有 EXISTS谓词的子查询 (续 )
[例 42] 查询没有选修 1号课程的学生姓名 。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno = Student.Sno
AND Cno='1');
此例用连接运算难于实现
带有 EXISTS谓词的子查询 (续 )
● 3,不同形式的查询间的替换
– 一些带 EXISTS或 NOT EXISTS谓词的子查询
不能被其他形式的子查询等价替换
– 所有带 IN谓词、比较运算符,ANY和 ALL谓
词的子查询都能用带 EXISTS谓词的子查询等
价替换。
带有 EXISTS谓词的子查询 (续 )
例,[例 37]可以用带 EXISTS谓词的子查询替换,
SELECT Sno,Sname,Sdept
FROM Student S1
WHERE EXISTS
(SELECT *
FROM Student S2
WHERE S2.Sdept = S1.Sdept AND
S2.Sname = ? 刘晨 ’ );
带有 EXISTS谓词的子查询 (续 )
● 4,相关子查询的效率
– 由于带 EXISTS量词的相关子查询只关心内
层查询是否有返回值,并不需要查具体值,
因此其效率并不一定低于其他形式的查询。
例 37:不相关子查询的效率高于相关子查询
的效率
带有 EXISTS谓词的子查询 (续 )
相关子查询的效率可能高于连接查询
例:查询选修了课程的学生姓名
法一,
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno);
带有 EXISTS谓词的子查询 (续 )
法二,
SELECT Sname
FROM Student,SC
WHERE Student.Sno=SC.Sno;
带有 EXISTS谓词的子查询 (续 )
法三,
SELECT Sname
FROM Student
WHERE sno in
(SELECT distinct sno
FROM SC);
带有 EXISTS谓词的子查询 (续 )
● 5.用 EXISTS/NOT EXISTS实现全称量词 (难点 )
– SQL语言中没有全称量词 ? ( For all)
– 可以把带有全称量词的谓词转换为等价的带有
存在量词的谓词,
(?x)P ≡ ? (? x(? P))
带有 EXISTS谓词的子查询 (续 )
[例 43] 查询选修了全部课程的学生姓名 。
SELECT Sname
FROM Student
WHERE NOT EXISTS
( SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno));
带有 EXISTS谓词的子查询 (续 )
6,用 EXISTS/NOT EXISTS实现逻辑蕴函 (难点 )
– SQL语言中没有蕴函 (Implication)逻辑运算
– 可以利用谓词演算将逻辑蕴函谓词等价转换
为,
p ? q ≡ ? p∨ q
带有 EXISTS谓词的子查询 (续 )
[例 44] 查询至少选修了学生 95002选修的全部
课程的学生号码。
解题思路,
● 用逻辑蕴函表达:查询学号为 x的学生,对所有的课程
y,只要 95002学生选修了课程 y,则 x也选修了 y。
● 形式化表示,
用 P表示谓词, 学生 95002选修了课程 y”
用 q表示谓词, 学生 x选修了课程 y”
则上述查询为, (?y) p ? q
带有 EXISTS谓词的子查询 (续 )
● 等价变换,
(?y)p ? q ≡ ? (?y (?(p ? q ))
≡ ? (?y (?(? p∨ q)
≡ ? ?y(p∧ ?q)
● 变换后语义:不存在这样的课程 y,学生 95002
选修了 y,而学生 x没有选。
带有 EXISTS谓词的子查询 (续 )
● 用 NOT EXISTS谓词表示,
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno = ' 95002 ' AND
NOT EXISTS
(SELECT *
FROM SC SCZ
WHERE SCZ.Sno=SCX.Sno AND
SCZ.Cno=SCY.Cno));
3.3 查 询
?3.3.1 单表查询
?3.3.2 连接查询
?3.3.3 嵌套查询
?3.3.4 集合查询
?3.3.5 小结
3.3.4 集合查询
?标准 SQL直接支持的集合操作种类
– 并操作 (UNION)
?一般商用数据库支持的集合操作种类
– 并操作 (UNION)
– 交操作 (INTERSECT)
– 差操作 (MINUS)
1,并操作
?形式
<查询块 >
UNION
<查询块 >
– 参加 UNION操作的各结果表的列数必须相
同;对应项的数据类型也必须相同
并操作(续)
[例 45] 查询计算机科学系的学生及年龄不大于 19
岁的学生。
方法一,
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19;
并操作(续)
方法二,
SELECT DISTINCT *
FROM Student
WHERE Sdept= 'CS' OR Sage<=19;
并操作(续)
[例 46] 查询选修了课程 1或者选修了课程 2的学生。
方法一,
SELECT Sno
FROM SC
WHERE Cno=' 1 '
UNION
SELECT Sno
FROM SC
WHERE Cno= ' 2 ';
并操作(续)
方法二,
SELECT DISTINCT Sno
FROM SC
WHERE Cno=' 1 ' OR Cno= ' 2 ';
并操作(续)
[例 47] 设数据库中有一教师表 Teacher(Tno,
Tname,...)。查询学校中所有师生的姓名。
SELECT Sname
FROM Student
UNION
SELECT Tname
FROM Teacher;
new
2,交操作
● 标准 SQL中没有提供集合交操作,但可
用其他方法间接实现。
2,交操作
[例 48] 查询计算机科学系的学生与年龄不大于 19
岁的学生的交集
本例实际上就是查询计算机科学系中年龄不大于
19岁的学生
SELECT *
FROM Student
WHERE Sdept= 'CS' AND
Sage<=19;
交操作(续)
[例 49] 查询选修课程 1的学生集合与选修课程 2的
学生集合的交集
本例实际上是查询既选修了课程 1又选修了课程 2
的学生
SELECT Sno
FROM SC
WHERE Cno=' 1 ' AND Sno IN
(SELECT Sno
FROM SC
WHERE Cno=' 2 ');
交操作(续)
[例 50] 查询学生姓名与教师姓名的交集
本例实际上是查询学校中与教师同名的学生姓名
SELECT DISTINCT Sname
FROM Student
WHERE Sname IN
(SELECT Tname
FROM Teacher); new
3,差操作
● 标准 SQL中没有提供集合差操作,但可
用其他方法间接实现。
3,差操作
[例 51] 查询计算机科学系的学生与年龄不大于 19
岁的学生的差集。
本例实际上是查询计算机科学系中年龄大于 19
岁的学生
SELECT *
FROM Student
WHERE Sdept= 'CS' AND
Sage>19;
差操作(续)
[例 52] 查询学生姓名与教师姓名的差集
本例实际上是查询学校中未与教师同名的学生
姓名
SELECT DISTINCT Sname
FROM Student
WHERE Sname NOT IN
(SELECT Tname
FROM Teacher);
new
4,对集合操作结果的排序
?ORDER BY子句只能用于对最终查询结
果排序,不能对中间结果排序
?任何情况下,ORDER BY子句只能出现
在最后
?对集合操作结果排序时,ORDER BY子
句中用数字指定排序属性
new
对集合操作结果的排序(续)
[例 53]
错误写法
SELECT *
FROM Student
WHERE Sdept= 'CS'
ORDER BY Sno
UNION
SELECT *
FROM Student
WHERE Sage<=19
ORDER BY Sno; new
对集合操作结果的排序(续)
正确写法
SELECT *
FROM Student
WHERE Sdept= 'CS'
UNION
SELECT *
FROM Student
WHERE Sage<=19
ORDER BY 1;
new
对集合操作结果的排序(续)
[例 54]
SELECT Sname,Sage,Sdept
FROM Student
UNION ALL
SELECT H_Sname,H_Sage,H_Sdept
FROM History_Student
ORDER BY 1;
new
3.3 查 询
?3.3.1 单表查询
?3.3.2 连接查询
?3.3.3 嵌套查询
?3.3.4 集合查询
?3.3.5 小结
3.3.5 小结
?SELECT语句的一般格式
SELECT [ALL|DISTINCT] <目标列表达式 >
[别名 ] [, <目标列表达式 > [别名 ]] …
FROM <表名或视图名 > [别名 ]
[, <表名或视图名 > [别名 ]] …
[WHERE <条件表达式 >]
[GROUP BY <列名 1>[,<列名 1?>],.,
[HAVING <条件表达式 >]]
[ORDER BY <列名 2> [ASC|DESC]
[,<列名 2?> [ASC|DESC] ] … ] ;
小结(续)
?目标列表达式
– 目标列表达式格式
(1) [ <表名 >.]*
(2) [<表名 >.]<属性列名表达式 >[,[<表名 >.]<
属性列名表达式 >] …
<属性列名表达式 >:由 属性列,作用于属性
列的 集函数 和 常量 的任意算术运算( +,-,
*,/)组成的运算公式。
小结(续)
– 集函数格式
COUNT
SUM
AVG ([DISTINCT|ALL] <列名 >)
MAX
MIN
COUNT ([DISTINCT|ALL] *)
小结(续)
?条件表达式格式
( 1)
<属性列名 >
<属性列名 > θ <常量 >
[ANY|ALL] (SELECT语句 )
小结(续)
( 2)
<属性列名 > <属性列名 >
<属性列名 > [NOT] BETWEEN <常量 > AND <常量 >
(SELECT (SELECT
语句 ) 语句 )
小结(续)
( 3) (<值 1>[,<值 2> ] …)
<属性列名 > [NOT] IN
(SELECT语句 )
小结(续)
(4) <属性列名 > [NOT] LIKE <匹配串 >
(5) <属性列名 > IS [NOT] NULL
(6) [NOT] EXISTS (SELECT语句 )
小结(续)
( 7) AND AND
<条件表达式 > <条件表达式 > <条件表达
> …
OR OR
第 3章 关系数据库标准语言 SQL
3.1 SQL概述
3.2 数据定义
3.3 查询
3.4 数据更新
3.5 视图
3.6 数据控制
3.7 嵌入式 SQL
3.8 小结
3.4 数 据 更 新
3.4.1 插入数据
3.4.2 修改数据
3.4.3 删除数据
3.4 数 据 更 新
3.4.1 插入数据
3.4.2 修改数据
3.4.3 删除数据
3.4.1 插入数据
?两种插入数据方式
– 插入单个元组
– 插入子查询结果
1,插入单个元组
? 语句格式
INSERT
INTO <表名 > [(<属性列 1>[,<属性列 2
>…)]
VALUES (<常量 1> [,<常量 2>]…)
– 功能
? 将新元组插入指定表中。
插入单个元组(续)
– INTO子句
? 指定要插入数据的表名及属性列
? 属性列的顺序可与表定义中的顺序不一致
? 没有指定属性列:表示要插入的是一条完整的元
组,且属性列属性与表定义中的顺序一致
? 指定部分属性列:插入的元组在其余属性列上取
空值
– VALUES子句
? 提供的值必须与 INTO子句匹配
> 值的个数
> 值的类型
插入单个元组(续)
?DBMS在执行插入语句时会检查所插元组
是否破坏表上已定义的完整性规则
– 实体完整性
– 参照完整性
– 用户定义的完整性
? 对于有 NOT NULL约束的属性列是否提供了非空值
? 对于有 UNIQUE约束的属性列是否提供了非重复值
? 对于有值域约束的属性列所提供的属性值是否在值
域范围内
插入单个元组(续)
[例 1] 将一个新学生记录(学号,95020;
姓名:陈冬;性别:男;所在系,IS;
年龄,18岁)插入到 Student表中。
INSERT
INTO Student
VALUES ('95020','陈冬 ','男 ','IS',18);
插入单个元组(续)
[例 2] 插入一条选课记录 ( '95020','1 ')。
INSERT
INTO SC(Sno,Cno)
VALUES (' 95020 ',' 1 ');
新插入的记录在 Grade列上取空值
2,插入子查询结果
?语句格式
INSERT INTO <表名 >
[(<属性列 1> [,<属性列 2>… )]
子查询;
– 功能
? 将子查询结果插入指定表中
插入子查询结果(续)
– INTO子句 (与插入单条元组类似 )
? 指定要插入数据的表名及属性列
? 属性列的顺序可与表定义中的顺序不一致
? 没有指定属性列:表示要插入的是一条完整的元

? 指定部分属性列:插入的元组在其余属性列上取
空值
– 子查询
? SELECT子句目标列必须与 INTO子句匹配
– 值的个数
– 值的类型
插入子查询结果(续)
?DBMS在执行插入语句时会检查所插元组是
否破坏表上已定义的完整性规则
– 实体完整性
– 参照完整性
– 用户定义的完整性
? 对于有 NOT NULL约束的属性列是否提供了非空值
? 对于有 UNIQUE约束的属性列是否提供了非重复值
? 对于有值域约束的属性列所提供的属性值是否在值
域范围内
插入子查询结果(续)
[例 3] 对每一个系,求学生的平均年龄,
并把结果存入数据库。
第一步:建表
CREATE TABLE Deptage
(Sdept CHAR(15) /* 系名 */
Avgage SMALLINT); /*学生平均年龄 */
插入子查询结果(续)
第二步:插入数据
INSERT
INTO Deptage(Sdept,Avgage)
SELECT Sdept,AVG(Sage)
FROM Student
GROUP BY Sdept;
3.4 数 据 更 新
3.4.1 插入数据
3.4.2 修改数据
3.4.3 删除数据
3.4.2 修改数据
?语句格式
UPDATE <表名 >
SET <列名 >=<表达式 >[,<列名 >=<表达式 >]…
[WHERE <条件 >];
– 功能
? 修改指定表中满足 WHERE子句条件的元组
修改数据(续)
– SET子句
? 指定修改方式
–要修改的列
–修改后取值
– WHERE子句
? 指定要修改的元组
–缺省表示要修改表中的所有元组
修改数据(续)
? DBMS在执行修改语句时会检查修改操作是否
破坏表上已定义的完整性规则
– 实体完整性
– 一些 DBMS规定主码不允许修改
– 用户定义的完整性
? NOT NULL约束
? UNIQUE约束
? 值域约束
修改数据(续)
?三种修改方式
– 修改某一个元组的值
– 修改多个元组的值
– 带子查询的修改语句
1,修改某一个元组的值
[例 4] 将学生 95001的年龄改为 22岁 。
UPDATE Student
SET Sage=22
WHERE Sno=' 95001 ';
2,修改多个元组的值
[例 5] 将所有学生的年龄增加 1岁 。
UPDATE Student
SET Sage= Sage+1;
修改多个元组的值 (续 )
[例 6] 将信息系所有学生的年龄增加 1岁 。
UPDATE Student
SET Sage= Sage+1
WHERE Sdept=' IS ';
3,带子查询的修改语句
[例 7] 将计算机科学系全体学生的成绩置零 。
UPDATE SC
SET Grade=0
WHERE 'CS'=
(SELETE Sdept
FROM Student
WHERE Student.Sno = SC.Sno);
带子查询的修改语句(续)
[例 7] 解法 2
UPDATE SC
SET Grade=0
WHERE SNO in
(SELETE Sno
FROM Student
WHERE Sdept = 'CS');
3.4 数 据 更 新
3.4.1 插入数据
3.4.2 修改数据
3.4.3 删除数据
3.4.3 删除数据
?语句格式
DELETE
FROM <表名 >
[WHERE <条件 >];
– 功能
?删除指定表中满足 WHERE子句条件的 元组
– WHERE子句
?指定要删除的元组
?缺省表示要修改表中的所有元组
删除数据 (续 )
?DBMS在执行删除语句时会检查所删元
组是否破坏表上已定义的完整性规则
– 参照完整性
? 不允许删除
? 级联删除
删除数据(续)
?三种删除方式
– 删除某一个元组的值
– 删除多个元组的值
– 带子查询的删除语句
1,删除某一个元组的值
[例 8] 删除学号为 95019的学生记录。
DELETE
FROM Student
WHERE Sno='95019';
2,删除多个元组的值
[例 9] 删除 2号课程的所有选课记录。
DELETE
FROM SC;
WHERE Cno='2';
[例 10] 删除所有的学生选课记录。
DELETE
FROM SC;
3,带子查询的删除语句
[例 11] 删除计算机科学系所有学生的选课记录。
DELETE
FROM SC
WHERE 'CS'=
(SELETE Sdept
FROM Student
WHERE Student.Sno=SC.Sno);
带子查询的删除语句(续)
[例 11] 解法 2
DELETE
FROM SC
WHERE SNO in
(SELETE Sno
FROM Student
WHERE Sdept = 'CS');
第 5章 关系数据库标准语言 SQL
3.1 SQL概述
3.2 数据定义
3.3 查询
3.4 数据更新
3.5 视图
3.6 数据控制
3.7 嵌入式 SQL
3.8 小结
3.5 视 图
? 视图的特点
– 虚表,是从一个或几个基本表(或视图)导出的表
– 只存放视图的定义,不会出现数据冗余
– 基表中的数据发生变化,从视图中查询出的数据也
随之改变
– 基于视图的操作
? 定义视图 (DDL)
– 建立
– 定义基于该视图的新视图
– 删除
? 查询 (DML)
? 受限更新 (DML)
3.5 视 图
3.5.1 定义视图
3.5.2 查询视图
3.5.3 更新视图
3.5.4 视图的作用
3.5 视 图
3.5.1 定义视图
3.5.2 查询视图
3.5.3 更新视图
3.5.4 视图的作用
3.5.1 定义视图
1,建立视图
2,删除视图
1,建立视图
?语句格式
CREATE VIEW <视图名 >
[(<列名 > [,<列名 >]…)]
AS <子查询 >
[WITH CHECK OPTION];
建立视图(续)
– 组成视图的属性列名或全部省略或全部指定
? 省略视图的各个属性列名,则隐含该视图由
子查询中 SELECT子句目标列中的诸字段组
成。
? 必须明确指定组成视图的所有列名的情形
(1) 某个目标列不是单纯的属性名,而是集函数或
列表达式
(2) 目标列为 *
(3) 多表连接时选出了几个同名列作为视图的字段
(4) 需要在视图中为某个列启用新的更合适的名字
建立视图(续)
– 子查询
? 不含 ORDER BY子句和 DISTINCT短语的
SELECT语句
– WITH CHECK OPTION
? 透过视图进行增删改操作时,不得破坏视
图定义中的谓词条件(即子查询中的条件
表达式)
建立视图(续)
?DBMS执行 CREATE VIEW语句时只是
把视图的定义存入数据字典,并不执行
其中的 SELECT语句。只是在对视图查
询时,才按视图的定义从基本表中将数
据查出。
建立视图(续)
?常见的视图形式
– 行列子集视图
– WITH CHECK OPTION的视图
– 基于多个基表的视图
– 基于视图的视图
– 带表达式的视图
– 分组视图
建立视图(续)
? 行列子集视图
– 从单个基本表导出
– 只是去掉了基本表的某些行和某些列,
但保留了码
建立视图(续)
[例 1] 建立信息系学生的视图。
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS';
行列子集视图视图 IS_Student由 Sno,Sname,
Sage三列组成
建立视图(续)
?WITH CHECK OPTION的视图
[例 2] 建立信息系学生的视图,并要求透过该视
图进行的更新操作只涉及信息系学生。
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS'
WITH CHECK OPTION;
建立视图(续)
– 对 IS_Student视图的更新操作
? 修改操作,DBMS自动加上 Sdept= 'IS'的
条件
? 删除操作,DBMS自动加上 Sdept= 'IS'的
条件
? 插入操作,DBMS自动检查 Sdept属性值
是否为 'IS'
–如果不是,则拒绝该插入操作
–如果没有提供 Sdept属性值,则自动定
义 Sdept为 'IS'
建立视图(续)
[例 3 ] 建立 1号课程的选课视图,并要求透过
该视图进行的更新操作只涉及 1号课程,同时
对该视图的任何操作只能在工作时间进行。
CREATE VIEW IS_SC
AS
SELECT Sno,Cno,Grade
FROM SC
WHERE Cno= '1'
AND TO_CHAR(SYSDATE,'HH24') BETWEEN 9 AND 17
AND TO_CHAR(SYSDATE,'D') BETWEEN 2 AND 6
WITH CHECK OPTION;
new
建立视图(续)
?基于多个基表的视图
[例 4] 建立信息系选修了 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,所以必须在视图名后面明确说明视
图的各个属性列名。
建立视图(续)
?基于视图的视图
[例 5] 建立信息系选修了 1号课程且成绩在 90分以上的
学生的视图。
CREATE VIEW IS_S2
AS
SELECT Sno,Sname,Grade
FROM IS_S1
WHERE Grade>=90;
– 视图 IS_S2建立在视图 IS_S1之上
建立视图(续)
?带表达式的视图
– 在设计数据库时,为了减少数据冗余,基本
表中只存放基本数据,由基本数据经过各种
计算派生出的数据一般是不存储的。
– 视图中的数据并不实际存储,所以定义视图
时可以根据应用的需要,设置一些派生属性
列,以方便应用程序的编制。
– 派生属性称为虚拟列。带虚拟列的视图称为
带表达式的视图。
– 带表达式的视图必须明确定义组成视图的各
个属性列名
建立视图(续)
[例 6] 定义一个反映学生出生年份的视图。
CREATE VIEW BT_S(Sno,Sname,Sbirth)
AS SELECT Sno,Sname,2002-Sage
FROM Student;
建立视图(续)
?分组视图
– 用带集函数和 GROUP BY子句的查询
来定义的视图称为分组视图
– 分组视图必须明确定义组成视图的各
个属性列名
建立视图(续)
[例 7] 将学生的学号及他的平均成绩定义
为一个视图。
假设 SC表中“成绩”列 Grade为数字型
CREAT VIEW S_G(Sno,Gavg)
AS SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
建立视图(续)
?一类不易扩充的视图
– 以 SELECT * 方式创建的视图可扩充性差,
应尽可能避免
建立视图(续)
[例 8]将 Student表中所有女生记录定义为一个视图
CREATE VIEW F_Student1
(stdnum,name,sex,age,dept)
AS SELECT *
FROM Student
WHERE Ssex='女 ';
修改基表 Student的结构后, Student表与 F_Student1
视图的映象关系被破坏, 导致该视图不能正确工作 。
建立视图(续)
CREATE VIEW F_Student2
(stdnum,name,sex,age,dept)
AS SELECT Sno,Sname,Ssex,Sage,Sdept
FROM Student
WHERE Ssex='女 ';
为基表 Student增加属性列不会破坏 Student表与
F_Student2视图的映象关系 。
2,删除视图
?语句格式
DROP VIEW <视图名 >;
– 该语句从数据字典中删除指定的视图定义
– 由该视图导出的其他视图定义仍在数据字典
中,但已不能使用,必须显式删除
– 删除基表时,由该基表导出的所有视图定义
都必须显式删除
删除视图 (续)
[例 9] 删除视图 IS_S1
DROP VIEW IS_S1;
执行此语句后, IS_S1视图的定义将从数据字典
中删除 。 由 IS_S1视图导出 IS_S2视图已无法使
用, 但其定义虽然仍在数据字典中 。
3.5 视 图
3.5.1 定义视图
3.5.2 查询视图
3.5.3 更新视图
3.5.4 视图的作用
3.5.2 查询视图
?从用户角度而言,查询视图与查询基本
表的方法相同
?DBMS实现视图查询的方法
– 视图实体化法( View Materialization)
? 进行有效性检查,检查所查询的视图是否存在。
如果存在,则从数据字典中取出视图的定义
? 执行视图定义,将视图临时实体化,生成临时表
? 将查询视图转换为查询临时表
? 查询完毕删除被实体化的视图 (临时表 ) new
查询视图(续)
– 视图消解法( View Resolution)
? 进行有效性检查,检查查询的表、视图等
是否存在。如果存在,则从数据字典中取
出视图的定义
? 把视图定义中的子查询与用户的查询结合
起来,转换成等价的对基本表的查询
? 执行修正后的查询
查询视图(续)
[例 1] 在信息系学生的视图中找出年龄小于 20岁
的学生。
SELECT Sno,Sage
FROM IS_Student
WHERE Sage<20;
IS_Student视图的定义 (视图定义例 1),
CREATE VIEW IS_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept= 'IS? ;
查询视图(续)
– 视图实体化法
– 视图消解法
转换后的查询语句为,
SELECT Sno,Sage
FROM Student
WHERE Sdept= 'IS' AND Sage<20;
查询视图(续)
[例 2] 查询信息系选修了 1号课程的学生
SELECT Sno,Sname
FROM IS_Student,SC
WHERE IS_Student.Sno=SC.Sno AND
SC.Cno= '1';
SQL模式图
S Q L 语言支持关系数据 库三级模 式结构
S Q L
视图 1 视图 2
基本表 1 基本表 2 基本表 4基本表 3
存储文件 1 存储文件 2
外模式
模 式
内模式
查询视图(续)
?视图消解法的局限
– 有些情况下,视图消解法不能生成正确查
询。采用视图消解法的 DBMS会限制这类查询。
查询视图(续)
[例 3] 在 S_G视图中查询平均成绩在 90分以上
的学生学号和平均成绩
SELECT *
FROM S_G
WHERE Gavg>=90;
查询视图(续)
S_G视图定义,
CREATE VIEW S_G (Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
查询视图(续)
转换后的查询,
SELECT Sno,AVG(Grade)
FROM SC
WHERE AVG(Grade)>=90
GROUP BY Sno;
查询视图(续)
正确转换,
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno
HAVING AVG(Grade)>=90;
3.5 视 图
3.5.1 定义视图
3.5.2 查询视图
3.5.3 更新视图
3.5.4 视图的作用
3.5.3 更新视图
?从用户角度而言,更新视图与更新基本
表的方法相同
?DBMS实现视图更新的方法
– 视图实体化法( View Materialization)
– 视图消解法( View Resolution)
更新视图(续)
?定义视图时指定 WITH CHECK
OPTION子句后,DBMS在更新视图时
会进行检查,防止用户通过视图对数据
进行增加、删除、修改时,操作不属于
视图范围内的基本表数据
更新视图(续)
[例 1] 将信息系学生视图 IS_Student中学号
为 95002的学生姓名改为“刘辰”。
UPDATE IS_Student
SET Sname= '刘辰 '
WHERE Sno= '95002';
更新视图(续)
– 视图实体化法
– 视图消解法
转换后的查询语句为,
UPDATE Student
SET Sname= '刘辰 '
WHERE Sno= '95002' AND Sdept= 'IS';
更新视图(续)
[例 2] 向信息系学生视图 IS_S中插入一个
新的学生记录,其中学号为 95029,姓名
为赵新,年龄为 20岁。
INSERT
INTO IS_Student
VALUES('95029','赵新 ',20);
更新视图(续)
转换为对基本表的更新,
INSERT
INTO Student(Sno,Sname,Sage,Sdept)
VALUES('95029','赵新 ',20,'IS' );
更新视图(续)
[例 3] 删除计算机系学生视图 CS_S中学号
为 95029的记录
DELETE
FROM IS_Student
WHERE Sno= '95029';
更新视图(续)
转换为对基本表的更新,
DELETE
FROM Student
WHERE Sno= '95029' AND Sdept= 'IS';
更新视图(续)
?DBMS对视图更新的限制
– 一些视图是不可更新的,因为对这些视图的
更新不能唯一地有意义地转换成对相应基本
表的更新 (对两类方法均如此 )
例:视图 S_G为不可更新视图。
CREATE VIEW S_G (Sno,Gavg)
AS
SELECT Sno,AVG(Grade)
FROM SC
GROUP BY Sno;
更新视图(续)
S_G,平均成绩” Gavg属性列为导出列
对于如下更新语句,
UPDATE S_G
SET Gavg=90
WHERE Sno= '95001';
无论实体化法还是消解法都无法将其转换成对基
本表 SC的更新的
更新视图(续)
– 视图的可更新性
? 行列子集视图是可更新的。
? 除行列子集视图外,还有些视图理论上是
可更新的,但它们的确切特征还是尚待研
究的课题。
? 还有些视图从理论上是不可更新的。
更新视图(续)
– 不可更新的视图与不允许更新的视图是两
个不同的概念
– 实际系统对视图更新的限制
?允许对行列子集视图进行更新
?对其他类型视图的更新不同系统有不同限

DB2对视图更新的限制,
(1) 若视图是由两个以上基本表导出的,则
此视图不允许更新。
更新视图(续)
(2) 若视图的字段来自字段表达式或常数,则
不允许对此视图执行 INSERT和 UPDATE
操作,但允许执行 DELETE操作。
(3) 若视图的字段来自集函数,则此视图不允
许更新。
(4) 若视图定义中含有 GROUP BY子句,则此
视图不允许更新。
(5) 若视图定义中含有 DISTINCT短语,则此
视图不允许更新。
更新视图(续)
(6) 若视图定义中有嵌套查询,并且内层查询的
FROM子句中涉及的表也是导出该视图的基本
表,则此视图不允许更新。
例:视图 GOOD_SC(修课成绩在平均成绩之上的元组 )
CREATE VIEW GOOD_SC
AS SELECT Sno,Cno,Grade
FROM SC
WHERE Grade >
(SELECT AVG(Grade)
FROM SC);
更新视图(续)
(7) 一个不允许更新的视图上定义的视图也不
允许更新。
3.5 视 图
3.5.1 定义视图
3.5.2 查询视图
3.5.3 更新视图
3.5.4 视图的作用
3.5.4 视图的作用
?视图最终是定义在基本表之上的,对视
图的一切操作最终也要转换为对基本表
的操作。而且对于非行列子集视图进行
查询或更新时还有可能出现问题。
视图的作用(续)
?合理使用视图能够带来许多好处
– 1,视图能够 简化 用户的 操作
– 2,视图使用户能以 多种角度 看待同一数据
– 3,视图对重构数据库提供了一定程度的 逻辑
独立性
– 4,视图能够对机密数据提供 安全保护
1,视图能够简化用户的操作
?当视图中数据不是直接来自基本表时,
定义视图能够简化用户的操作
– 基于多张表连接形成的视图
– 基于复杂嵌套查询的视图
– 含导出属性的视图
2,视图使用户能以多种角度看待同一数据
?视图机制能使不同用户以不同方式看待
同一数据,适应数据库共享的需要
3,视图对重构数据库提供了一定程
度的逻辑独立性
?物理独立性与逻辑独立性的概念
?视图在一定程度上保证了数据的逻辑独
立性
视图对重构数据库提供了一定程度的逻辑独立性(续)
例:数据库逻辑结构发生改变
将学生关系
Student(Sno,Sname,Ssex,Sage,Sdept)
“垂直”地分成两个基本表,
SX(Sno,Sname,Sage)
SY(Sno,Ssex,Sdept)
视图对重构数据库提供了一定程度的逻辑独立性(续)
通过建立一个视图 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;
使用户的外模式保持不变,从而对原 Student表
的查询程序不必修改
视图对重构数据库提供了一定程度的逻辑独立性(续)
?视图只能在一定程度上提供数据的逻辑
独立性
– 由于对视图的更新是有条件的,因此应用程
序中修改数据的语句可能仍会因基本表结构
的改变而改变。
4,视图能够对机密数据提供安全保护
?对不同用户定义不同视图,使每个用户
只能看到他有权看到的数据
?通过 WITH CHECK OPTION对关键数
据定义操作时间限制
第 3章 关系数据库标准语言 SQL
3.1 SQL概述
3.2 数据定义
3.3 查询
3.4 数据更新
3.5 视图
3.6 数据控制
3.7 嵌入式 SQL
3.8 小结
3.6 数据控制
?概述
?授权
?收回权限
?小结
概述
数据控制亦称为数据保护, 包括数据的,
?安全性控制
?完整性控制
?并发控制
?恢复
SQL语言的数据控制功能
SQL语言提供了数据控制功能, 能够在一
定程度上保证数据库中数据的完全性,
完整性, 并提供了一定的并发控制及恢
复能力 。
1,完整性
?数据库的完整性是指数据库中数据的正
确性与相容性。
?SQL语言定义完整性约束条件
CREATE TABLE语句
ALTER TABLE语句
? 码
? 取值唯一的列
? 参照完整性
? 其他约束条件
2,并发控制
?并发控制指的是当多个用户并发地对数
据库进行操作时,对他们加以控制、协
调,以保证并发操作正确执行,并保持
数据库的一致性。
?SQL语言提供了并发控制能力。
3,恢复
?恢复指的是当发生各种类型的故障,使
数据库处于不一致状态时,将数据库恢
复到一致状态的功能。
?SQL语言提供了恢复的功能,支持事务、
提交、回滚等概念。
4,安全性
?数据库的安全性是指保护数据库, 防止
不合法的使用所造成的数据泄露和破坏 。
?数据库系统保证数据安全性的主要措施
– 进行存取控制, 即规定不同用户对于不同
数据对象所允许执行的操作, 并控制各用户
只能存取他有权存取的数据
安全性 (续 )
?DBMS实现数据安全性保护的过程
– 用户或 DBA把授权决定告知系统, 这是由
SQL的 GRANT和 REVOKE语句来完成的
– DBMS把授权的结果存入数据字典
– 当用户提出操作请求时, DBMS根据授权情
况进行检查, 以决定是否执行操作请求
安全性 (续 )
?不同的用户对不同的数据应具有何种操
作权力,是由 DBA和表的建立者(即表的
属主)根据具体情况决定的,SQL语言则
为 DBA和表的属主定义与回收这种权力提
供了手段。
?SQL的安全性控制能力
– 授 权
– 回收权力
一,SQL的授 权功能
?GRANT语句的一般格式,
GRANT <权限 >[,<权限 >]..,
[ON <对象类型 > <对象名 >]
TO <用户 >[,<用户 >]..,
[WITH GRANT OPTION];
?功能:将对指定操作对象的指定操作权
限授予指定的用户 。
(1) 操作权限
(2) 用户的权限
?数据库的建立表 ( CREATETAB) 的权限属
于 DBA,可由 DBA授予普通用户, 普通用
户拥有此权限后可以建立基本表 。
?基本表或视图的属主拥有对该表或视图
的一切操作权限 。
(3) 接受权限的用户
?一个或多个具体用户
?PUBLIC(全体用户)
(4) WITH GRANT OPTION子句
?如果指定了 WITH GRANT OPTION子句,则
获得某种权限的用户还可以把这种权限
再授予别的用户。
?如果没有指定 WITH GRANT OPTION子句,
则获得某种权限的用户只能使用该权限,
但不能传播该权限
例题
例 1 把查询 Student表权限授给用户 U1
GRANT SELECT
ON TABLE Student
TO U1;
例题(续)
例 2 把对 Student表和 Course表的全部权限
授予用户 U2和 U3
GRANT ALL PRIVILIGES
ON TABLE Student,Course
TO U2,U3;
例题(续)
例 3 把对表 SC的查询权限授予所有用户
GRANT SELECT
ON TABLE SC
TO PUBLIC;
例题(续)
例 4 把查询 Student表和修改学生姓名的
权限授给用户 U4
GRANT UPDATE(Sname),SELECT
ON TABLE Student
TO U4;
例题(续)
例 5 把对表 SC的 INSERT权限授予 U5用户,
并允许他再将此权限授予其他用户
GRANT INSERT
ON TABLE SC
TO U5
WITH GRANT OPTION;
传播权限
执行例 5后, U5不仅拥有了对表 SC的
INSERT权限, 还可以传播此权限,
GRANT INSERT ON TABLE SC TO U6
WITH GRANT OPTION;
同样, U6还可以将此权限授予 U7,
GRANT INSERT ON TABLE SC TO U7;
但 U7不能再传播此权限 。
例题(续)
例 6 DBA把在数据库 S_C中建立表的权限授
予用户 U8
GRANT CREATETAB
ON DATABASE S_C
TO U8;
GRANT语句 小结
?一次向一个用户授权 ( 例 1) 这是最简单
的一种授权操作;
?一次向多个用户授权 ( 例 2,例 3) ;
?一次传播多个同类对象的权限 (例 2) ;
?一次可以完成对基本表, 视图和属性列
这些不同对象的授权 ( 例 4) ;
?授予关于 DATABASE的权限必须与授予关
于 TABLE的权限分开 。
二,SQL收回权限的功能
?REVOKE语句的一般格式为,
REVOKE <权限 >[,<权限 >]..,
[ON <对象类型 > <对象名 >]
FROM <用户 >[,<用户 >]...;
?功能:从指定用户那里收回对指定对象
的指定权限
例题
例 7 把用户 U4修改学生学号的权限收回
REVOKE UPDATE(Sno)
ON TABLE Student
FROM U4;
例题(续)
例 8 收回所有用户对表 SC的查询权限
REVOKE SELECT
ON TABLE SC
FROM PUBLIC;
例题(续)
例 9 把用户 U5对 SC表的 INSERT权限收回
REVOKE INSERT
ON TABLE SC
FROM U5;
权限的级联回收
系统将收回直接或间接从 U5处获得的对 SC
表的 INSERT权限
小结
SQL提供了非常灵活的授权机制
?用户对自己建立的基本表和视图拥有全
部的操作权限, 并且可以用 GRANT语句把
其中某些权限授予其他用户 。
?被授权的用户如果有, 继续授权, 的许
可, 还可以把获得的权限再授予其他用
户 。
小结(续)
?DBA拥有对数据库中所有对象的所有权限,
并可以根据应用的需要将不同的权限授
予不同的用户。
?所有授予出去的权力在必要时又都可以
用 REVOKE语句收回。
第 3章 关系数据库标准语言 SQL
3.1 SQL概述
3.2 数据定义
3.3 查询
3.4 数据更新
3.5 视图
3.6 数据控制
3.7 嵌入式 SQL
3.8 小结
三类可编程 SQL
?嵌入式 SQL
?用 API编程 (Application Programming
Interface)
– ODBC
– JDBC
– Specific API
?PL/SQL
3.7 嵌 入 式 SQL
3.7.1 嵌入式 SQL的一般形式
3.7.2 嵌入式 SQL语句与主语言之间的通信
3.7.3 不用游标的 SQL语句
3.7.4 使用游标的 SQL语句
3.7.5 动态 SQL简介
3.7 嵌 入 式 SQL
?SQL语言的两种使用方式
– 交互式 SQL
– 嵌入式 SQL
?为什么要引入嵌入式 SQL
– SQL语言是非过程性语言
3.7 嵌 入 式 SQL
3.7.1 嵌入式 SQL的一般形式
3.7.2 嵌入式 SQL语句与主语言之间的通信
3.7.3 不用游标的 SQL语句
3.7.4 使用游标的 SQL语句
3.7.5 动态 SQL简介
3.7.1 嵌入式 SQL的一般形式
?DBMS处理宿主型数据库语言 SQL 的方法
– 预编译
– 修改和扩充主语言使之能处理 SQL语句
嵌入式 SQL的一般形式 (续 )
?预编译
1.由 DBMS的预处理程序对源程序进行扫描,
识别出 SQL语句
2.把它们转换成主语言调用语句,以使主
语言编译程序能识别它
3.最后由主语言的编译程序将整个源程序
编译成目标码。
嵌入式 SQL的一般形式 (续 )
?嵌入式 SQL语句的一般形式
– 为了能够区分 SQL语句与主语言语句,需要
为 SQL语句加前缀和结束标志
? 前缀,EXEC SQL
? 结束标志:随主语言的不同而不同
嵌入式 SQL的一般形式 (续 )
– 以 C或 PL/1作为主语言的嵌入式 SQL语句的
一般形式
EXEC SQL <SQL语句 >;
例,EXEC SQL DROP TABLE Student;
嵌入式 SQL的一般形式 (续 )
– 以 COBOL作为主语言的嵌入式 SQL语句的
一般形式
EXEC SQL <SQL语句 > END-EXEC
例,
EXEC SQL DROP TABLE Student END-EXEC
嵌入式 SQL的一般形式 (续 )
?嵌入 SQL语句的分类,
– 分类依据:根据语句作用的不同
– 分类
说明性语句
嵌入 SQL语句 数据定义
可执行语句 数据控制
数据操纵
嵌入式 SQL的一般形式 (续 )
– 使用方法
? 任何允许出现可执行的高级语言语
句的地方,都可以写可执行 SQL语

? 任何允许出现说明性高级语言语句
的地方,都可以写说明性 SQL语句
3.7 嵌 入 式 SQL
3.7.1 嵌入式 SQL的一般形式
3.7.2 嵌入式 SQL语句与主语言之间的通信
3.7.3 不用游标的 SQL语句
3.7.4 使用游标的 SQL语句
3.7.5 动态 SQL简介
3.7.2 嵌入式 SQL语句与主语言之间的通信
?将 SQL嵌入到高级语言中混合编程,程
序中会含有两种不同计算模型的语句
– SQL语句
? 描述性的面向集合的语句
? 负责操纵数据库
– 高级语言语句
? 过程性的面向记录的语句
? 负责控制程序流程
嵌入式 SQL语句与主语言之间的通信(续)
?数据库工作单元与主语言程序工作单元
之间的通信方式
– 1,SQL通信区:传递执行状态
? 向主语言传递 SQL语句的执行状态信息,使主语
言能够据此控制程序流程
– 2,主变量:传递数据
? 1)主语言向 SQL语句提供参数
? 2)将 SQL语句查询数据库的结果交主语言进一
步处理
– 3,游标
? 解决集合性操作语言与过程性操作语言的不匹配
1,SQL通信区
?什么是 SQLCA
– SQLCA,SQL Communication Area
– SQLCA是一个数据结构
SQL通信区(续)
?SQLCA的用途
– SQL语句执行后,DBMS将反馈给应用程序
若干信息
? 描述系统当前工作状态
? 描述运行环境
– 这些信息将送到 SQL通信区 SQLCA中
– 应用程序从 SQLCA中取出这些状态信息,
据此决定接下来执行的语句
SQL通信区(续)
? SQLCA的内容
– 与所执行的 SQL语句有关
– 与该 SQL语句的执行情况有关
例:在执行删除语句 DELETE后,根据不同的执行情况,
SQLCA中有下列不同的信息,
? 违反数据保护规则,操作拒绝
? 没有满足条件的行,一行也没有删除
– SQL%NOTFOUND=TRUE
? 成功删除,删除 X行数
– SQL%FOUND=TRUE
– SQL%ROWCOUNT=X
? 无条件删除警告信息
? 由于各种原因,执行出错
SQL通信区(续)
?SQLCA的使用方法
– 定义 SQLCA
? 用 EXEC SQL INCLUDE SQLCA加以定义
– 使用 SQLCA
? SQLCA中有一个存放每次执行 SQL语句后返回
代码的变量 SQLCODE
? 如果 SQLCODE等于预定义的常量 SUCCESS,
则表示 SQL语句成功,否则表示出错
? 应用程序每执行完一条 SQL 语句之后都应该测
试一下 SQLCODE的值,以了解该 SQL语句执行
情况并做相应处理
2,主变量
?什么是主变量
– 嵌入式 SQL语句中可以使用主语言的程序变
量来输入或输出数据
– 在 SQL语句中使用的主语言程序变量简称为
主变量( Host Variable)
主变量(续)
?主变量的类型
– 输入主变量
? 由应用程序对其赋值,SQL语句引用
– 输出主变量
? 由 SQL语句赋值或设置状态信息,返回给
应用程序
– 一个主变量有可能既是输入主变量又是输出
主变量
主变量(续)
?主变量的用途
– 输入主变量
? 指定向数据库中插入的数据
? 将数据库中的数据修改为指定值
? 指定执行的操作
? 指定 WHERE子句或 HAVING子句中的
条件
– 输出主变量
? 获取 SQL语句的结果数据
? 获取 SQL语句的执行状态
主变量(续)
?指示变量
– 一个主变量可以附带一个指示变量
( Indicator Variable)
– 什么是指示变量
? 整型变量
? 用来“指示”所指主变量的值或条件
– 指示变量的用途
? 输入主变量可以利用指示变量赋空值
? 输出主变量可以利用指示变量检测出是否
空值,值是否被截断
主变量(续)
?在 SQL语句中使用主变量和指示变量的
方法
– 1) 说明主变量和指示变量
BEGIN DECLARE SECTION
,.......,
,.......,(说明主变量和指示变量 )
,.......,
END DECLARE SECTION
主变量(续)
– 2) 使用主变量
? 说明之后的主变量可以在 SQL语句中任何
一个能够使用表达式的地方出现
? 为了与数据库对象名(表名、视图名、列
名等)区别,SQL语句中的主变量名前要
加冒号(,)作为标志
主变量(续)
– 3) 使用指示变量
? 指示变量前也必须加冒号标志
? 必须紧跟在所指主变量之后
主变量(续)
?在 SQL语句之外 (主语言语句中 )使用主变
量和指示变量的方法
– 可以直接引用,不必加冒号
3,游标( cursor)
?为什么要使用游标
– SQL语言与主语言具有不同数据处理方式
?SQL语言是面向集合的,一条 SQL语句
原则上可以产生或处理多条记录
游标(续)
?主语言是面向记录的,一组主变量一次
只能存放一条记录
– 仅使用主变量并不能完全满足 SQL语句向应
用程序输出数据的要求
– 嵌入式 SQL引入了游标的概念,用来协调这
两种不同的处理方式
游标(续)
? 什么是游标
– 游标是系统为用户开设的一个数据缓冲区,
存放 SQL语句的执行结果
– 每个游标区都有一个名字
– 用户可以用 SQL语句逐一从游标中获取记录,
并赋给主变量,交由主语言进一步处理
嵌入式 SQL语句与主语言之间的通信 (续 )
?小结
– 在嵌入式 SQL中,SQL语句与主语言语句分
工非常明确
? SQL语句:直接与数据库打交道
? 主语言语句
1,控制程序流程
2,对 SQL语句的执行结果做进一步
加工处理
嵌入式 SQL语句与主语言之间的通信 (续 )
– SQL语句用主变量从主语言中接收执行参数,
操纵数据库
– SQL语句的执行状态由 DBMS送至 SQLCA中
– 主语言程序从 SQLCA中取出状态信息,据
此决定下一步操作
– 如果 SQL语句从数据库中成功地检索出数据,
则通过主变量传给主语言做进一步处理
– SQL语言和主语言的不同数据处理方式通过
游标来协调
嵌入式 SQL语句与主语言之间的通信 (续 )
例:带有嵌入式 SQL的一小段 C程序
,..........,
EXEC SQL INCLUDE SQLCA;
/* (1) 定义 SQL通信区 */
EXEC SQL BEGIN DECLARE SECTION;
/* (2) 说明主变量 */
CHAR title_id (7);
CHAR title (81);
INT royalty;
EXEC SQL END DECLARE SECTION;
嵌入式 SQL语句与主语言之间的通信 (续 )
main()
{
EXEC SQL DECLARE C1 CURSOR FOR
SELECT tit_id,tit,roy FROM titles;
/* (3) 游标操作(定义游标) */
/* 从 titles表中查询 tit_id,tit,roy */
EXEC SQL OPEN C1;
/* (4) 游标操作(打开游标) */
嵌入式 SQL语句与主语言之间的通信 (续 )
for(;;)
{
EXEC SQL FETCH C1 INTO,title_id,:title,:royalty;
/* (5) 游标操作(将当前数据放入主变量并推进游标指针) */
if (sqlca.sqlcode <> SUCCESS)
/* (6) 利用 SQLCA中的状态信息决定何时退出循环 */
break;
printf("Title ID,%s,Royalty,%d",title_id,royalty);
printf("Title,%s",title);
/* 打印查询结果 */
}
EXEC SQL CLOSE C1;
/* (7) 游标操作(关闭游标) */
}
3.7 嵌 入 式 SQL
3.7.1 嵌入式 SQL的一般形式
3.7.2 嵌入式 SQL语句与主语言之间的通信
3.7.3 不用游标的 SQL语句
3.7.4 使用游标的 SQL语句
3.7.5 动态 SQL简介
3.7.3 不用游标的 SQL语句
?不用游标的 SQL语句的种类
– 说明性语句
– 数据定义语句
– 数据控制语句
– 查询结果为单记录的 SELECT语句
– 非 CURRENT形式的 UPDATE语句
– 非 CURRENT形式的 DELETE语句
– INSERT语句
一、说明性语句
?说明性语句是专为在嵌入式 SQL中说明
主变量,SQLCA等而设置的
?说明主变量
1,EXEC SQL BEGIN DECLARE SECTION;
2,EXEC SQL END DECLARE SECTION;
– 这两条语句必须配对出现,相当于一个括号,
两条语句中间是主变量的说明
?说明 SQLCA
3,EXEC SQL INCLUDE SQLCA
二、数据定义语句
例 1 建立一个“学生”表 Student
EXEC SQL CREATE TABLE Student
(Sno CHAR(5) NOT NULL UNIQUE,
Sname CHAR(20),
Ssex CHAR(1),
Sage INT,
Sdept CHAR(15));
数据定义语句(续)
?数据定义语句中不允许使用主变量
例:下列语句是错误的
EXEC SQL DROP
TABLE,table_name;
三、数据控制语句
例 2 把查询 Student表权限授给用户 U1
EXEC SQL GRANT SELECT ON
TABLE Student TO U1;
四、查询结果为单记录的 SELECT语句
? 语句格式
EXEC SQL SELECT [ALL|DISTINCT]
<目标列表达式 >[,<目标列表达式 >]..,
INTO <主变量 >[<指示变量 >]
[,<主变量 >[<指示变量 >]]..,
FROM <表名或视图名 >[,<表名或视图名 >],.,
[WHERE <条件表达式 >]
[GROUP BY <列名 1> [HAVING <条件表达式 >]]
[ORDER BY <列名 2> [ASC|DESC]];
查询结果为单记录的 SELECT语句(续)
– 对交互式 SELECT语句的扩充就是多了一个
INTO子句
? 把从数据库中找到的符合条件的记录,放
到 INTO子句指出的主变量中去。
查询结果为单记录的 SELECT语句(续)
? 使用注意事项
– 1,使用主变量
? INTO子句
? WHERE子句的条件表达式
? HAVING短语的条件表达式
查询结果为单记录的 SELECT语句(续)
– 2,使用指示变量
? 指示变量只能用于 INTO子句中
? 指示变量取值
– 0:相应的主变量取正常值
– -1:相应的主变量取空值
– >0:相应的主变量取正常值,但因主变量取
值超长,其值被四舍五入(数值型)或截断
(字符型)
查询结果为单记录的 SELECT语句(续)
– 2,使用指示变量(续)
? 如果 INTO子句中主变量后面跟有指示变
量,则当查询得出的某个数据项为空值时,
系统会自动将相应主变量后面的指示变量
置为负值,但不向该主变量执行赋值操作,
即主变量值仍保持执行 SQL语句之前的值
? 当发现指示变量值为负值时,不管主变量
为何值,均应认为主变量值为 NULL
查询结果为单记录的 SELECT语句(续)
– 3,查询结果为空集
? 如果数据库中没有满足条件的记录,即查
询结果为空,则 DBMS将 SQLCODE的值
置为 100
– 4,查询结果为多条记录
? 程序出错,DBMS会在 SQLCA中返回错
误信息
查询结果为单记录的 SELECT语句(续)
例 3 根据学生号码查询学生信息。
假设已将要查询的学生的学号赋给了主变量 givensno
EXEC SQL SELECT Sno,Sname,Ssex,Sage,Sdept
INTO,Hsno,:Hname,:Hsex,:Hage,:Hdept
FROM Student
WHERE Sno=:givensno;
– Hsno,Hname,Hsex,Hage,Hdept和 givensno均是主
变量,并均已在前面的程序中说明过了。
查询结果为单记录的 SELECT语句(续)
例 4 查询某个学生选修某门课程的成绩。
假设已将要查询的学生的学号赋给了主变量
givensno,将课程号赋给了主变量 givencno。
EXEC SQL SELECT Sno,Cno,Grade
INTO,Hsno,:Hcno,:Hgrade:Gradeid
FROM SC
WHERE Sno=:givensno AND Cno=:givencno;
查询结果为单记录的 SELECT语句(续)
?从提高应用程序的数据独立性角度考虑,
SELECT语句在任何情况下都应该使用
游标
– 对于仅返回一行结果数据的 SELECT语句虽
然可以不使用游标
– 但如果以后数据库改变了,该 SELECT语句
可能会返回多行数据,这时该语句就会出错
五、非 CURRENT形式的 UPDATE语句
?非 CURRENT形式的 UPDATE语句
– 使用主变量
? SET子句
? WHERE子句
– 使用指示变量
? SET子句
?非 CURRENT形式的 UPDATE语句可以操
作多条元组
非 CURRENT形式的 UPDATE语句(续)
例 5 将全体学生 1号课程的考试成绩增加若
干分。
假设增加的分数已赋给主变量 Raise
EXEC SQL UPDATE SC
SET Grade=Grade+:Raise
WHERE Cno='1';
非 CURRENT形式的 UPDATE语句(续)
例 6 修改某个学生 1号课程的成绩。
假设该学生的学号已赋给主变量 givensno,
修改后的成绩已赋给主变量 newgrade。
EXEC SQL UPDATE SC
SET Grade=:newgrade
WHERE Sno=:givensno
AND Cno='1';
非 CURRENT形式的 UPDATE语句(续)
例 7 将计算机系全体学生年龄置 NULL值
Sageid=-1;
EXEC SQL UPDATE Student
SET Sage=:Raise:Sageid
WHERE Sdept='CS';
非 CURRENT形式的 UPDATE语句(续)
– 将指示变量 Sageid赋一个负值后,无论主变
量 Raise为何值,DBMS都会将 CS系所有记
录的年龄属性置空值。它等价于,
EXEC SQL UPDATE Student
SET Sage=NULL
WHERE Sdept='CS';
六、非 CURRENT形式的 DELETE语句
?非 CURRENT形式的 DELETE语句
– 使用主变量
? WHERE子句
?非 CURRENT形式的 DELETE语句可以
操作多条元组
非 CURRENT形式的 DELETE语句(续)
例 8 某个学生退学了,现要将有关他的所有选课
记录删除掉。
假设该学生的姓名已赋给主变量 stdname
EXEC SQL DELETE
FROM SC
WHERE Sno=
(SELECT Sno
FROM Student
WHERE Sname=:stdname);
七,INSERT语句
?INSERT语句
– 使用主变量
? VALUES子句
– 使用指示变量
? VALUES子句
?INSERT语句一次只能输入一条元组
INSERT语句(续)
例 9 某个学生新选修了某门课程,将有关记录插入 SC表
假设学生的学号已赋给主变量 stdno,课程号已赋给主
变量 couno。
gradeid=-1;
EXEC SQL INSERT
INTO SC
VALUES(:stdno,:couno,:gr:gradeid);

EXEC SQL INSERT
INTO SC(Sno,Cno)
VALUES(:stdno,:couno);
3.7.4 使用游标的 SQL语句
? 必须使用游标的 SQL语句
– 查询结果为多条记录的 SELECT语句
– CURRENT形式的 UPDATE语句
– CURRENT形式的 DELETE语句
一,查询结果为多条记录的 SELECT语句
?使用游标的步骤
– 1,说明游标
– 2,打开游标
– 3,移动游标指针,然后取当前记录
– 4,关闭游标
1,说明游标
?使用 DECLARE语句
?语句格式
EXEC SQL DECLARE <游标名 > CURSOR
FOR <SELECT语句 >;
?功能
– 是一条说明性语句,这时 DBMS并不执行
SELECT指定的查询操作。
2,打开游标
?使用 OPEN语句
?语句格式
EXEC SQL OPEN <游标名 >;
?功能
– 打开游标实际上是执行相应的 SELECT语句,
把所有满足查询条件的记录从指定表取到缓
冲区中
– 这时游标处于活动状态,指针指向查询结果
集中第一条记录 之前
3,移动游标指针,然后取当前记录
?使用 FETCH语句
?语句格式
EXEC SQL FETCH [[NEXT|PRIOR|
FIRST|LAST] FROM] <游标名 >
INTO <主变量 >[<指示变量 >]
[,<主变量 >[<指示变量 >]]...;
移动游标指针,然后取当前记录(续)
?功能
– 按指定方向推动游标指针,然后将缓冲区中
的当前记录取出来送至主变量供主语言进一
步处理。
– NEXT|PRIOR|FIRST|LAST:指定推动游标
指针的方式。
? NEXT:向前推进一条记录
? PRIOR:向回退一条记录
? FIRST:推向第一条记录
? LAST:推向最后一条记录
? 缺省值为 NEXT
移动游标指针,然后取当前记录(续)
?说明
– (1) 主变量必须与 SELECT语句中的目标列
表达式具有一一对应关系
– (2) FETCH语句通常用在一个循环结构中,
通过循环执行 FETCH语句逐条取出结果集
中的行进行处理
– (3) 为进一步方便用户处理数据,现在一些
关系数据库管理系统对 FETCH语句做了扩
充,允许用户向任意方向以任意步长移动游
标指针
4,关闭游标
?使用 CLOSE语句
?语句格式
EXEC SQL CLOSE <游标名 >;
?功能
– 关闭游标,释放结果集占用的缓冲区及其他资源
?说明
– 游标被关闭后,就不再和原来的查询结果集
相联系
– 被关闭的游标可以再次被打开,与新的查询
结果相联系
例题
例 1 查询某个系全体学生的信息(学号、姓名、
性别和年龄)。要查询的系名由用户在程序运
行过程中指定,放在主变量 deptname中
,....,
,....,
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
例题(续)
,....,
/* 说明主变量 deptname,HSno,HSname,HSsex,
HSage等 */
,....,
,....,
EXEC SQL END DECLARE SECTION;
,....,
,....,
gets(deptname); /* 为主变量 deptname赋值 */
,....,
例题(续)
EXEC SQL DECLARE SX CURSOR FOR
SELECT Sno,Sname,Ssex,Sage
FROM Student
WHERE SDept=:deptname; /* 说明游标 */
EXEC SQL OPEN SX /* 打开游标 */
例题(续)
WHILE(1) /* 用循环结构逐条处理结果集中的记录 */
{
EXEC SQL FETCH SX
INTO,HSno,:HSname,:HSsex,:HSage;
/* 将游标指针向前推进一行,然后从结
果集中取当前行,送相应主变量 */
例题(续)
if (sqlca.sqlcode <> SUCCESS)
break;
/* 若所有查询结果均已处理完或出现
SQL语句错误,则退出循环 */
/* 由主语言语句进行进一步处理 */
,....,
,....,
};
例题(续)
EXEC SQL CLOSE SX; /* 关闭游标 */
,....,
,....,
例题(续)
例 2 查询某些系全体学生的信息。
,....,
,....,
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
,....,
/* 说明主变量
deptname,HSno,HSname,HSsex,HSage等 */
,....,
,....,
例题(续)
EXEC SQL END DECLARE SECTION;
,....,
,....,
,....,
EXEC SQL DECLARE SX CURSOR FOR
SELECT Sno,Sname,Ssex,Sage
FROM Student
WHERE SDept=:deptname; /* 说明游标 */
例题(续)
WHILE (gets(deptname)!=NULL) /* 接收主变量
deptname的值 */
{
/* 下面开始处理 deptname指定系的学生信息,
每次循环中 deptname可具有不同的值 */
EXEC SQL OPEN SX /* 打开游标 */
例题(续)
WHILE (1) { /* 用循环结构逐条处理结果集中的记录
*/
EXEC SQL FETCH SX
INTO,HSno,:HSname,:HSsex,:HSage;
/* 将游标指针向前推进一行,然后从结果集中
取当前行,送相应主变量 */
例题(续)
if (sqlca.sqlcode <> SUCCESS)
break;
/* 若所有查询结果均已处理完或出现
SQL语句错误,则退出循环 */
/* 由主语言语句进行进一步处理 */
,....,
,....,
}; /* 内循环结束 */
例题(续)
EXEC SQL CLOSE SX; /* 关闭游标 */
}; /* 外循环结束 */
,....,
,....,
二,CURRENT形式的 UPDATE语句和 DELETE语句
?CURRENT形式的 UPDATE语句和
DELETE语句的用途
– 非 CURRENT形式的 UPDATE语句和
DELETE语句
? 面向集合的操作
? 一次修改或删除所有满足条件的记录
二,CURRENT形式的 UPDATE语句和 DELETE语句
?CURRENT形式的 UPDATE语句和
DELETE语句的用途(续)
– 如果只想修改或删除其中某个记录
? 用带游标的 SELECT语句查出所有满足条
件的记录
? 从中进一步找出要修改或删除的记录
? 用 CURRENT形式的 UPDATE语句和
DELETE语句修改或删除之
CURRENT形式的 UPDATE语句和 DELETE语句(续)
?步骤
– (1) DECLARE
? 说明游标
– (2) OPEN
? 打开游标,把所有满足查询条件的记录
从指定表取至缓冲区
– (3) FETCH
? 推进游标指针,并把当前记录从缓冲区中
取出来送至主变量
CURRENT形式的 UPDATE语句和 DELETE语句(续)
?说明游标
– 为 UPDATE语句说明游标
? 使用带 FOR UPDATE OF <列名 >短语的
DECLARE语句
? 语句格式
EXEC SQL DECLARE <游标名 > CURSOR
FOR <SELECT语句 > FOR UPDATE
OF <列名 >;
? FOR UPDATE OF <列名 >短语用于指明
检索出的数据在指定列上是可修改的,以
便 DBMS进行并发控制
CURRENT形式的 UPDATE语句和 DELETE语句(续)
– 为 DELETE语句说明游标
? 使用带 FOR UPDATE短语的 DECLARE
语句
? 语句格式
EXEC SQL DECLARE <游标名 > CURSOR
FOR <SELECT语句 > FOR UPDATE;
? FOR UPDATE短语提示 DBMS进行并发
控制
CURRENT形式的 UPDATE语句和 DELETE语句(续)
– (4) 检查该记录是否是要修改或删除的
记录,是则处理之
– (5) 重复第 (3)和 (4)步,用逐条取出结果
集中的行进行判断和处理
– (6) CLOSE
? 关闭游标,释放结果集占用的缓冲区和
其他资源
CURRENT形式的 UPDATE语句和 DELETE语句(续)
?修改或删除当前记录
– 经检查缓冲区中记录是要修改或删除的记录,
则用 UPDATE语句或 DELETE语句修改或删
除该记录
– 语句格式
? <UPDATE语句 > WHERE CURRENT OF <游标名 >
? <DELETE语句 > WHERE CURRENT OF <游标名 >
– WHERE CURRENT OF <游标名 >子句表示修改
或删除的是该游标中最近一次取出的记录
CURRENT形式的 UPDATE语句和 DELETE语句(续)
?当游标定义中的 SELECT语句带有
UNION或 ORDER BY子句时,或者该
SELECT语句相当于定义了一个不可更
新的视图时,不能使用 CURRENT形式
的 UPDATE语句和 DELETE语句
例题
例 3 对某个系的学生信息,根据用户的要
求修改其中某些人的年龄字段。
– 思路
? 查询某个系全体学生的信息 (要查询的系
名由主变量 deptname指定)
? 然后根据用户的要求修改其中某些记录
的年龄字段
例题(续)
,....,
,....,
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
,....,
/* 说明主变量
deptname,HSno,HSname,HSsex,HSage,NEWAge等 */
,....,
例题(续)
,....,
EXEC SQL END DECLARE SECTION;
,....,
,....,
gets(deptname); /* 为主变量 deptname赋值 */
,....,
例题(续)
EXEC SQL DECLARE SX CURSOR FOR
SELECT Sno,Sname,Ssex,Sage
FROM Student
WHERE SDept=:deptname
FOR UPDATE OF Sage; /* 说明游标 */
EXEC SQL OPEN SX /* 打开游标 */
例题(续)
WHILE(1) {/* 用循环结构逐条处理结果集中的记录 */
EXEC SQL FETCH SX INTO,HSno,:HSname,
,HSsex,:HSage;
/* 将游标指针向前推进一行,然后从结果集
中取当前行,送相应主变量 */
例题(续)
if (sqlca.sqlcode <> SUCCESS)
break;
/* 若所有查询结果均已处理完或
出现 SQL语句错误,则退出循环 */
printf("%s,%s,%s,%d",HSno,HSname,HSsex,
HSage);
/* 显示该记录 */
printf("UPDATE AGE? "); /* 问用户是否要修改 */
scanf("%c",&yn);
例题(续)
if (yn='y' or yn='Y') /* 需要修改 */
{
printf("INPUT NEW AGE,");
scanf("%d",&NEWAge); /* 输入新的年龄值 */
EXEC SQL UPDATE Student
SET Sage=:NEWAge
WHERE CURRENT OF SX;
/* 修改当前记录的年龄字段 */
};
例题(续)
,....,
,....,
};
EXEC SQL CLOSE SX; /* 关闭游标 */
,....,
,....,
例题(续)
例 4 对某个系的学生信息,根据用户的要求删
除其中某些人的记录。
,....,
,....,
EXEC SQL INCLUDE SQLCA;
EXEC SQL BEGIN DECLARE SECTION;
,....,
/* 说明主变量
deptname,HSno,HSname,HSsex,HSage等 */
例题(续)
,....,
,....,
EXEC SQL END DECLARE SECTION;
,....,
,....,
gets(deptname); /* 为主变量 deptname赋值 */
,....,
例题(续)
EXEC SQL DECLARE SX CURSOR FOR
SELECT Sno,Sname,Ssex,Sage
FROM Student
WHERE SDept=:deptname
FOR UPDATE; /* 说明游标 */
EXEC SQL OPEN SX /* 打开游标 */
例题(续)
WHILE(1){ /* 用循环结构逐条处理结果集中的记
录 */
EXEC SQL FETCH SX INTO,HSno,:HSname,
,HSsex,:HSage;
/* 将游标指针向前推进一行,然后从结
果集中取当前行,送相应主变量 */
例题(续)
if (sqlca.sqlcode <> SUCCESS)
break;
/* 若所有查询结果均已处理完或
出现 SQL语句错误,则退出循环 */
printf("%s,%s,%s,%d",HSno,HSname,HSsex,
HSage);
/* 显示该记录 */
例题(续)
printf("DELETE? "); /* 问用户是否要删除 */
scanf("%c",&yn);
if (yn='y' or yn='Y') /* 需要删除 */
EXEC SQL DELETE
FROM Student
WHERE CURRENT OF SX; /* 删除当前记录 */
例题(续)
,....,
,....,
};
EXEC SQL CLOSE SX; /* 关闭游标 */
,....,
,....,
3.7 嵌 入 式 SQL
3.7.1 嵌入式 SQL的一般形式
3.7.2 嵌入式 SQL语句与主语言之间的通信
3.7.3 不用游标的 SQL语句
3.7.4 使用游标的 SQL语句
3.7.5 动态 SQL简介
3.7.5 动态 SQL简介
?静态嵌入式 SQL
?动态嵌入式 SQL
一、静态 SQL
?1,静态嵌入式 SQL的特点
– 用户可以在程序运行过程中根据实际需要输
入 WHERE子句或 HAVING子句中某些变量
的值。
– 语句中主变量的个数与数据类型在预编译时
都是确定的,只有是主变量的值是程序运行
过程中动态输入的。
静态 SQL(续)
?2.静态 SQL的不足
– 静态 SQL语句提供的编程灵活性在许多情况
下仍显得不足,不能编写更为通用的程序。
静态 SQL(续)
例,查询学生选课关系 SC,
任课教师想查选修某门课程的所有学生的学
号及其成绩
班主任想查某个学生选修的所有课程的课程
号及相应成绩
学生想查某个学生选修某门课程的成绩
即:查询条件是不确定的,要查询的属性列
也是不确定的
二、动态 SQL
?1,什么是动态嵌入式 SQL
– 动态 SQL方法允许在程序运行过程中临时
“组装” SQL语句。
?2,应用范围
– 在预编译时下列信息不能确定时
? SQL语句正文
? 主变量个数
? 主变量的数据类型
? SQL语句中引用的数据库对象(列、索引、基
本表、视图等)
动态 SQL(续)
?3,动态 SQL的形式
– 语句可变
? 临时构造完整的 SQL语句
– 条件可变
? WHERE子句中的条件
? HAVING短语中的条件
– 数据库对象、查询条件均可变
? SELECT子句中的列名
? FROM子句中的表名或视图名
? WHERE子句中的条件
? HAVING短语中的条件
动态 SQL(续)
?4,常用动态 SQL语句
– EXECUTE IMMEDIATE
– PREPARE
– EXECUTE
– DESCRIBE
?使用动态 SQL技术更多的是涉及程序设
计方面的知识,而不是 SQL语言本身
例,
静态 SQL,
EXEC SQL BEGIN DECLARE SECTION
float increment;
EXEC SQL END DECLARE SECTION
EXEC SQL UPDATE staff SET salary= salary+:increment
WHERE staffNo =“1021”
动态 SQL,
EXEC SQL BEGIN DECLARE SECTION;
char buffer[100];
float increment;
EXEC SQL END DECLARE SECTION;
sprintf (buffer,“UPDATE staff SET salary =
UPDATE staff SET salary =salary+%f
WHERE staffNo =?1021?”,increment);
EXEC SQL EXECUTE IMMEDIATE,buffer;
第 3章 关系数据库标准语言 SQL
3.1 SQL概述
3.2 数据定义
3.3 查询
3.4 数据更新
3.5 视图
3.6 数据控制
3.7 嵌入式 SQL
3.8 小结
3.10 小结
?SQL的特点
– ⒈ 综合统一
– 2,高度非过程化
– 3,面向集合的操作方式
– 4,同一种语法结构提供两种使用方式
– 5,语言简捷,易学易用
小结(续)
?交互式 SQL
– 数据定义
– 查询
– 数据更新
– 数据控制
小结(续)
表 3, 1 S Q L 语言的动词
S Q L 功能 动 词
数 据 查 询 S E L E C T
数 据 定 义 C R E A T E, D R O P, A L T E R
数 据 操 纵 I N S E R T, U P D A T E,
D E L E T E
数 据 控 制 G R A N T, R E V O K E
小结(续)
?嵌入式 SQL
– 与主语言的通信方式
? 1,SQL通信区
– 向主语言传递 SQL语句的执行状态信息
? 2,主变量
– 1)主语言向 SQL语句提供参数
– 2)将 SQL语句查询数据库的结果交主语言进
一步处理
? 3,游标
– 解决集合性操作语言与过程性操作语言的不
匹配
小结(续)
?嵌入式 SQL(续 )
– 静态 SQL
? 不用游标
– 不需要返回结果数据的 SQL语句
– 只返回一条结果的 SQL语句
? 使用游标
– 说明游标
– 打开游标
– 推进游标并取当前记录
– 关闭游标
– 动态 SQL
小结(续)
?PL/SQL
?ODBC
– ODBC的工作原理和系统构成
– ODBC驱动程序管理器和驱动程序的主要功能
– ODBC应用系统工作流程