1
关系数据库标准语言 SQL
2
SQL语言的主要特点之一,
?SQL是一种一体化的语言,它包括了数据
定义、数据查询、数据操纵和数据控制
等方面的功能,它可以完成数据库活动
中的全部工作。而以前的非关系模型的
数据语言一般包括存储模式描述语言、
概念模式描述语言、外部模式描述语言
和数据操纵语言等等,这种模型的数据
语言,一是内容多,二是掌握和使用起
来都不象 SQL那样简单、实用。
3
SQL语言的主要特点之二,
?SQL语言是一种高度非过程化的语言,它没
有必要一步步地告诉计算机“如何”去做,
而只需要描述清楚用户要“做什么”,SQL
语言就可以将要求交给系统,自动完成全
部工作。
4
SQL语言的主要特点之三,
?SQL语言非常简洁,虽然 SQL语言功能很强,但它
只有为数不多的几条命令,下表给出了分类的命
令动词,另外 SQL的语法也非常简单,它很接近
自然语言(英语),因此容易学习、掌握。
5
SQL语言的主要特点之四,
?SQL语言可以直接以命令方式交互使用,
也可以嵌入到程序设计语言中以程序方
式使用。现在很多数据库应用开发工具,
都将 SQL语言直接溶入到自身的语言之中,
使用起来更方便。这些使用方式为用户
提供了灵活的选择余地。此外,尽管 SQL
的使用方式不同,但 SQL语言的语法基本
是一致的。
6
SQL的数据定义功能
?基本表的定义
?视图的定义
?索引的定义
CREATE TABLE
DROP TABLE
ALTER TABLE
CREATE VIEW
DROP VIEW
CREATE INDEX
DROP INDEX
7
基本表定义:
CREATE TABLE <表名 >(
<列名 > <数据类型 > [<列级完整性约束 >],
<列名 > <数据类型 > [<列级完整性约束 >],
……,
[<表级完整性约束 >]
) [<其它参数 >]
?<表名 >给出要创建的基本表的名称;
?<列名 >给出列名或字段名;
?<数据类型 >
?<列级完整性约束 >
?<表级完整性约束 >
?<其它参数 >
8
数据类型
?为列指定数据
类型及其数据
宽度;
?关系数据库支
持非常丰富的
数据类型,不
同的数据库管
理系统支持的
数据类型基本
是一样的,右
表列出了常用
的数据类型。
9
列级完整性约束
?用于定义列或字段一级的完整性约束,一般包括:
?NOT NULL和 NULL约束
?PRIMARY KEY约束
?UNIQUE约束
?FOREIGN KEY约束
?DEFAULT定义
?CHECK约束
10
表级完整性约束
?用于定义表一级的完整性约束,一般包括:
?PRIMARY KEY约束(复合属性构成的主关
键字说明)
?FOREIGN KEY约束(外部关键字及参照关系
说明)
?CHECK约束(同时涉及到多个属性的域完整
性约束)
11
其它参数
?不是 SQL的标准选项,一般用于与物理存
储有关的说明,不同的数据库管理系统定
义的方式肯定不同,另外该项参数一般也
不是必需的。
12
建立表的例子 仓库
职工
供应商
订购单
13
例,建立仓库表
CREATE TABLE 仓库 (
仓库号 CHAR(5) PRIMARY KEY,
城市 CHAR(10),
面积 INT CHECK (面积 > 0) )
14
例,建立职工表
CREATE TABLE 职工 (
仓库号 CHAR(5) FOREIGN KEY REFERENCES 仓库,
职工号 CHAR(5) PRIMARY KEY,
工资 INT CHECK (工资 >= 1000 AND 工资 <= 5000)
DEFAULT 1200 )
15
例,建立供应商表
CREATE TABLE 供应商 (
供应商号 CHAR(5) PRIMARY KEY,
供应商名 CHAR(20),
地址 CHAR(20))
16
例,建立订购单表
CREATE TABLE 订购单 (
职工号 CHAR(5) NOT NULL FOREIGN KEY REFERENCES 职工,
供应商号 CHAR(5) NULL FOREIGN KEY REFERENCES 供应商,
订购单号 CHAR(5) PRIMARY KEY,
订购日期 DATETIME DEFAULT getdate())
17
表级约束的例子
? 假设职工关系的主关键字是 ( 仓库号,职工号 ),
则相应的命令如下:
CREATE TABLE 职工 (
仓库号 CHAR(5) FOREIGN KEY REFERENCES 仓库,
职工号 CHAR(5),
工资 INT CHECK (工资 >= 1000 AND 工资 <= 5000)
DEFAULT 1200,
PRIMARY KEY (仓库号,职工号 ))
18
修改表结构命令
ALTER TABLE <表名 >
ADD <列名 > <数据类型 > [<列级完整性约束 >] |
DROP <完整性约束名 > |
DROP COLUMN <列名 > |
ALTER COLUMN <列名 > <数据类型 > [<列级完整性约束 >]
? 增加新的属性(字段)
? 修改属性的定义
? 删除完整性约束
? 删除属性
19
增加新的属性(字段)
?往订购单关系中增加一个新属性“完成日期”
ALTER TABLE 订购单
ADD 完成日期 DATETIME NULL
20
修改属性的定义
?将订购单关系的完成日期属性的数据类型修改为
SMALLDATETIME
ALTER TABLE 订购单
ALTER COLUMN 完成日期 SMALLDATETIME NULL
21
删除完整性约束
?建立的列级或表级完整性约束可以删除,但是前提是在定义完整
性约束时必须给出约束名称,否则不能删除。
设有:
CREATE TABLE 职工 (
仓库号 CHAR(5) FOREIGN KEY (仓库号 ) REFERENCES仓库 (仓库号 ),
职工号 CHAR(5) PRIMARY KEY,
工资 INT CONSTRAINT salary CHECK (工资 >= 1000 AND 工资 <= 5000)
DEFAULT 1200 )
则可以:
ALTER TABLE 职工 DROP CONSTRAINT salary
22
删除属性
删除订购单关系中的“完成日期”属性:
ALTER TABLE 订购单 DROP COLUMN 完成日期
注意,有些系统的 ALTER TABLE命令不允许删除属性,如果
必须要删除属性,一般步骤是:先将旧表中的数据备份,然后
删除旧表、并建立新表,最后将原来的数据恢复到新表中。
23
删除表
命令格式:
DROP TABLE <表名 >
例,DROP TABLE 订购单
24
索引定义的命令格式
CREATE [ UNIQUE ] [ CLUSTERED ]
INDEX <索引名 >
ON <表名 >(<列名 > [ ASC | DESC ]
[,<列名 > [ ASC | DESC ]…] )
? 普通索引
? 唯一( UNIQUE)索引
? 聚集( CLUSTERED)索引
25
普通索引
? 如果没有指定 UNIQUE或 CLUSTERED等将建立普
通索引。
在单个字段上建立普通索引:
CREATE INDEX sup_idx ON 订购单 (供应商号 )
在多个字段上建立普通索引:
CREATE INDEX sup_emp_idx
ON 订购单 (供应商号,职工号 DESC)
26
唯一索引
?通过指定 UNIQUE则为表创建唯一索引(不允许存在索
引值相同的两个元组)。
?在 CREATE TABLE命令中的 UNIQUE约束将隐式创建唯
一索引。
?在仓库关系的城市属性上建立一个唯一索引:
CREATE UNIQUE INDEX city_idx ON 仓库 (城市 )
27
聚集索引
?通过指定 CLUSTERED建立聚集索引。(索引值与关系
中元组的顺序物理相同 )。
?在 CREATE TABLE命令中的 PRIMARY KEY约束将隐式
创建聚集索引。
?一个表只允许建立一个聚集索引。
?如果在创建表时已经指定了主关键字,则不可以再创建
聚集索引。
28
使用索引的原则:
不应该在一个表上建立太多的索引(一
般不超过两到三个),索引能改善查询效果,
但也耗费了磁盘空间,降低了更新操作的性
能,因为系统必须花时间来维护这些索引。
除了为数据的完整性而建立的唯一索引外,
建议在表较大时再建立普通索引,表中的数
据越多,索引的优越性才越明显。
29
索引的删除
命令格式:
DROP INDEX <索引名 >
例,DROP INDEX sup_emp_idx
30
SQL的数据查询功能
基本格式:
SELECT ……
FROM ……
WHERE ……
31
SQL查询命令格式
SELECT [ALL|DISTINCT] {*|<表达式 >,…,<表达式 >}
FROM <表名 >[,<表名 >…]
[WHERE <条件 >]
[GROUP BY <列名 >[,<列名 >…][HAVING < 谓词 >]]
[ORDER BY <列名 > [ASC|DESC] [,<列名 > [ASC|DESC]…]
[COMPUTE …]
32
SELECT [ALL|DISTINCT] {*|<表达式 >,…,<表达式 >}
?说明要查询的数据,ALL说明不去掉重复元组,
DISTINCT说明要去掉重复元组,<表达式 > 一
般是表中的列名,如果要查询表中的所有列可
以使用,*”表示
33
FROM <表名 >[,<表名 >… ]
?说明要查询的数据来自哪个(些)表,可以基
于单个表或多个表进行查询
34
WHERE <逻辑表达式 >
?说明查询条件,即选择元组的条件,可以用于查
询条件的运算符也非常丰富,下表列出了常用的
运算符
35
GROUP BY <列名 >[,<列名 >… ] [HAVING <谓词 >]
?GROUP BY短语用于对查询结果进行分组,可以利
用它进行分组汇总;
?HAVING短语必须跟随 GROUP BY使用,它用来限
定分组必须满足的条件。
36
ORDER BY <列名 > [ASC|DESC],[ <列名 > [ASC|DESC]]…
?用来对查询的结果进行排序。
37
COMPUTE短语
?SQL Server支持的短语,可以进行带明细的汇总。
?SQL Server支持的短语,可以进行带明细的分组
汇总。
COMPUTE BY短语
38
SQL 92标准中的 SQL SELECT语句格式
SELECT <属性或表达式列表 >
FROM <关系 1> JOIN <关系 2> [JOIN <关系 3>… ]
[[ON … ]
[ON <连接条件 2>]]
ON <连接条件 1>
WHERE <查询条件 >
GROUP BY… HAVING …
ORDER BY…
?注意, JOIN的顺序和 ON的顺序是逆着的 。
39
查询的分类
?简单查询
?排序
?连接查询
?嵌套查询
?分组及计算查询
40
简单查询
?基于单个关系、简单条件的查询。
?从职工关系中检索所有工资值 。
?检索仓库关系中的所有元组 。
?检索工资多于 1230元的职工号 。
?检索 哪些仓库有工资多于 1210元的职工 。
?给出在仓库 WH1或 WH2工作,并且工资少于 1250元的职工号 。
?检索出工资在 1220元到 1240元范围内的职工信息 。
?从供应商关系中检索出全部公司的信息 (不要工厂或其他供
应商的信息)。
?找出不在北京的全部供应商信息 。
?找出尚未确定供应商的订购单 。
?列出已经确定了供应商的订购单信息 。
41
从职工关系中检索所有工资值
SELECT 工资 FROM 职工
结果是:
1220
1210
1250
1230
1250
SELECT DISTINCT工资 FROM 职工
结果是:
1220
1210
1250
1230
42
检索仓库关系中的所有元组
SELECT * FROM 仓库
SELECT 仓库号,城市,面积 FROM 仓库
43
检索工资多于 1230元的职工号
SELECT 职工号
FROM 职工
WHERE 工资 > 1230
结果是:
E4
E7
44
检索 哪些仓库有工资多于 1210元的职工
SELECT DISTINCT 仓库号
FROM 职工
WHERE 工资 > 1210
结果是:
WH2
WH3
WH1
45
给出在仓库 WH1或 WH2工作,并且工资少
于 1250元的职工号
SELECT 职工号
FROM 职工
WHERE 工资 < 1250 AND (仓库号 ='WH1' OR 仓库号 ='WH2')
结果是:
E1
E3
46
检索出工资在 1220元到 1240元范围内的职工信息
SELECT *
FROM 职工
WHERE 工资 BETWEEN 1220 AND 1240
结果是:
WH2 E1 1220
WH3 E6 1230
表达式“工资 BETWEEN 1220 AND 1240,等价于
(工资 >= 1220) AND (工资 <= 1240)
47
从供应商关系中检索出全部公司的信息
SELECT *
FROM 供应商
WHERE 供应商名 LIKE '%公司 '
结果是:
S4 华通电子公司 北京
这里的 LIKE是字符串匹配运算符,通配符,%”表示
0个或多个字符,另外还有一个通配符,_”(下划线)表
示一个字符。
48
找出不在北京的全部供应商信息
SELECT *
FROM 供应商
WHERE 地址 != '北京 '

SELECT *
FROM 供应商
WHERE NOT (地址 = '北京 ')
结果是:
S3 振华电子厂 西安
S6 607 厂 郑州
NOT的应用范围很广,比如,可以有 NOT IN,NOT
BETWEEN等。
49
找出尚未确定供应商的订购单
SELECT *
FROM 订购单
WHERE 供应商号 IS NULL
结果是:
E6 NULL OR77 NULL
E1 NULL OR80 NULL
E3 NULL OR90 NULL
注意,查询空值时要使用 IS NULL,而 =NULL 是无
效的,因为空值不是一个确定的值,所以不能用,=”这
样的运算符进行比较。
50
列出已经确定了供应商的订购单信息
SELECT *
FROM 订购单
WHERE 供应商号 IS NOT NULL
结果是:
E3 S3 OR91 2002-07-13 00:00:00.000
E7 S4 OR76 2002-05-25 00:00:00.000
E3 S4 OR79 2002-06-13 00:00:00.000
E1 S4 OR73 2002-07-28 00:00:00.000
E3 S7 OR67 2002-06-23 00:00:00.000
51
排序
?可以对查询的结果进行排序,可以是升序
或降序,可以按多列排序。
?按职工的工资值升序检索出全部职工信息
?先按仓库号排序,再按工资排序并输出全部职
工信息
52
按职工的工资值升序检索出全部职工信息
SELECT *
FROM 职工
ORDER BY 工资
结果是:
WH1 E3 1210
WH2 E1 1220
WH3 E6 1230
WH2 E4 1250
WH1 E7 1250
53
先按仓库号排序再按工资排序输出全部职工信息
SELECT *
FROM 职工
ORDER BY 仓库号,工资
结果是:
WH1 E3 1210
WH1 E7 1250
WH2 E1 1220
WH2 E4 1250
WH3 E6 1230
54
连接查询
?当查询的结果出自多个表时,需要通过表
之间的连接操作来完成。
?一般连接
?别名和自连接查询
?广义笛卡尔积
?内连接
?外连接
55
一般连接
?常规的两个表或多个表之间的连接。
?找出工资多于 1230元的职工号和他们所在的城市
?找出工作在面积大于 400的仓库的职工号以及这些职
工工作所在的城市
?给出有北京仓库订购单的北京供应商的名称
56
找出工资多于 1230元的职工号和他们所在的城市
SELECT 职工号,城市
FROM 职工,仓库
WHERE (工资 > 1230)
AND (职工,仓库号 = 仓库,仓库号 )
SELECT 职工号,城市
FROM 职工 JOIN 仓库
ON 职工,仓库号 = 仓库,仓库号
WHERE 工资 > 1230
结果是:
E4 上海
E7 北京
57
找出工作在面积大于 400的仓库的职工号
以及这些职工工作所在的城市
SELECT 职工号,城市
FROM 仓库,职工
WHERE (面积 > 400)
AND (职工,仓库号 = 仓库,仓库号 )
SELECT 职工号,城市
FROM 职工 JOIN 仓库
ON 职工,仓库号 = 仓库,仓库号
WHERE 面积 > 400
结果是:
E1 上海
E4 上海
58
给出有北京仓库订购单的北京供应商的名称
SELECT 供应商名
FROM 供应商,订购单,职工,仓库
WHERE地址 ='北京 ' AND 城市 ='北京 '
AND 供应商,供应商号 =订购单,供应商号
AND 订购单,职工号 =职工,职工号
AND 职工,仓库号 =仓库,仓库号
SELECT 供应商名
FROM 供应商 JOIN 订购单 JOIN 职工 JOIN 仓库
ON 职工,仓库号 =仓库,仓库号
ON 订购单,职工号 =职工,职工号
ON 供应商,供应商号 =订购单,供应商号
WHERE 地址 ='北京 ' AND 城市 ='北京 '
59
别名和自连接查询
?一个表通过不同的属性到自身的连接称作自连接。
?这种 关系中的一些元组,根据出自同一值域的两个不同
的属性,可以与另外一些元组有一种对应关系(一对多
的联系)。
?为了实现自连接需要将一个关系看作两个逻辑关系,为
此需要给关系指定别名。
60
自连接查询
?设有如下图所示的雇员关系,其中雇员号和经理两个属性出
自同一个值域,同一元组的这两个属性值是“上、下级”关
系。
查询:根据雇员关系列出上一级经理及其职员(被其领导)的清单。
SELECT S.雇员姓名,?领导’,E.雇员姓名
FROM 雇员 S,雇员 E
WHERE S.雇员号 = E.经理
结果是:
赵涌 领导 钱潮
赵涌 领导 孙洁
孙洁 领导 李渌
61
广义笛卡尔积
?在新的 SQL标准中还支持广义笛卡尔积( CROSS)
运算,SQL Server也支持该运算。
?广义笛卡尔积( CROSS)运算的一般格式是:
SELECT <属性或表达式列表 >
FROM <表名 > CROSS JOIN <表名 >
[WHERE <限定条件 >]
?其中 FROM <表名 > CROSS JOIN <表名 >指出了广
义笛卡尔积运算,如下命令将得到纯粹的广义笛卡
尔积运算的结果:
SELECT * FROM <表名 > CROSS JOIN <表名 >
62
广义笛卡尔积运算实例
? 得到仓库关系和职工关系的广义笛卡尔积的运算结果
SELECT * FROM 仓库 CROSS JOIN 职工
? 对仓库关系和职工关系进行传统的连接
SELECT * FROM 仓库 CROSS JOIN 职工
WHERE 仓库,仓库号 =职工,仓库号
结果是:
WH2 上海 500 WH2 E1 1220
WH1 北京 370 WH1 E3 1210
WH2 上海 500 WH2 E4 1250
WH3 广州 200 WH3 E6 1230
WH1 北京 370 WH1 E7 1250
63
内连接
?在新的 SQL标准中内连接( INNER)运算的一般格式是:
SELECT <属性或表达式列表 >
FROM <表名 > [INNER] JOIN <表名 >
ON <连接条件 >
[WHERE <限定条件 >]
?内连接就是就是传统的连接操作,其中 INNER可以省略,这里
用 ON短语指定连接条件,用 WHERE短语指定其它限定条件。
64
外连接
? 外连接与前面所介绍的等值连接和自然连接不同。原
来的连接是只有满足连接条件,相应的结果才会出现在
结果表中;而外连接可以使不满足连接条件的元组也出
现在结果表中。
? 按连接方式外连接又可以分为左连接( LEFT)、右连
接( RIGHT)和全连接( FULL)三种。
65
外连接( OUTER)运算的一般格式
?左连接在结果表中包含第一个表中满足条件的所有记录;如
果是在连接条件上匹配的元组,则第二个表返回相应值,否
则第二个表返回空值。
?右连接在结果表中包含第二个表中满足条件的所有记录;如
果是在连接条件上匹配的元组,则第一个表返回相应值,否
则第一个表返回空值。
?全连接在结果表中包含两个表中满足条件的所有记录;如果
是在连接条件上匹配的元组,则另一个表返回相应值,否则
另一个表返回空值。
SELECT <属性或表达式列表 >
FROM <表名 > LEFT | RIGHT | FULL [OUTER] JOIN <表名 >
ON <连接条件 >
[WHERE <限定条件 >]
66
举例
? 设有仓库和职工两个关系,如果是等值或自
然连接
SELECT 仓库,仓库号,城市,面积,职工号,工资
FROM 仓库 JOIN 职工
ON 仓库,仓库号 =职工,仓库号
结果是:
WH2 上海 500 E1 1220
WH1 北京 370 E3 1210
WH2 上海 500 E4 1250
WH3 广州 200 E6 1230
WH1 北京 370 E7 1250
67
举例
? 设有仓库和职工两个关系,如果是左连接
SELECT 仓库,仓库号,城市,面积,职工号,工资
FROM 仓库 LEFT JOIN 职工
ON 仓库,仓库号 =职工,仓库号
结果是:
WH1 北京 370 E3 1210
WH1 北京 370 E7 1250
WH2 上海 500 E1 1220
WH2 上海 500 E4 1250
WH3 广州 200 E6 1230
WH4 武汉 400 NULL NULL
68
嵌套查询
?普通嵌套查询
?使用量词的嵌套查询
?内、外层互相关嵌套查询
?使用 EXISTS的嵌套查询
69
普通嵌套查询
?当检索关系 X中的元组时,它的条件依赖于相关的关
系 Y中的元组的属性值,这时使用普通的嵌套查询将非
常方便。
?哪些城市至少有一个仓库的职工的工资为 1250元?
?找出和职工 E4挣同样工资的所有职工 。
?找出 哪些城市的仓库向北京的供应商发出了订购单 。
70
哪些城市至少有一个仓库的职工的工资为 1250元?
SELECT 城市
FROM 仓库
WHERE 仓库号 IN (SELECT 仓库号
FROM 职工
WHERE 工资 = 1250 )
结果是:
北京
上海
71
找出和职工 E4挣同样工资的所有职工。
SELECT 职工号
FROM 职工
WHERE 工资 = (SELECT 工资
FROM 职工
WHERE 职工号 =,E4” )
结果是:
E4
E7
72
找出 哪些城市的仓库向北京的供应商发出了订购单
SELECT 城市 FROM 仓库 WHERE 仓库号 IN
(SELECT 仓库号 FROM 职工 WHERE 职工号 IN
(SELECT 职工号 FROM 订购单 WHERE 供应商号 IN
(SELECT 供应商号 FROM 供应商 WHERE 地址 ='北京 ')))
结果是:
北京
上海
73
使用量词的嵌套查询
?在嵌套查询中可以使用 ANY,SOME,ALL等量词, 它
们的形式是:
<表达式 > <比较运算符 > [ANY|ALL|SOME] (子查询 )
?其中 ANY和 SOME是同义词, 在进行比较运算时只要子
查询中有一行能使结果为真, 则结果就为真;而 ALL则
要求子查询中的所有行都使结果为真时, 结果才为真 。
74
检索有职工的工资大于或等于 WH1仓库中任何一名职工的工资的仓库号
SELECT DISTINCT 仓库号 FROM 职工
WHERE 工资 >= ANY (SELECT 工资 FROM 职工
WHERE 仓库号 = 'WH1')
SELECT DISTINCT 仓库号 FROM 职工
WHERE 工资 >= (SELECT MIN(工资 ) FROM 职工
WHERE 仓库号 = 'WH1')
等价于:
结果是:
WH1
WH2
WH3
75
检索有职工的工资大于或等于 WH1仓库中所有职工的工资的仓库号
SELECT DISTINCT 仓库号 FROM 职工
WHERE 工资 >= ALL (SELECT 工资 FROM 职工
WHERE 仓库号 = 'WH1')
SELECT DISTINCT 仓库号 FROM 职工
WHERE 工资 >= (SELECT MAX(工资 ) FROM 职工
WHERE 仓库号 = 'WH1')
等价于:
结果是:
WH1
WH2
76
内、外层互相关嵌套查询
?一般的嵌套查询都是外层查询依赖于内层
查询的结果,而内层查询与外层查询无关。
?事实上,有时也需要内、外层互相关的查
询,即内层查询需要外层查询提供数据,
而外层查询又依赖内层查询的结果。
77
在订购单关系中加入一个新字段 总金额,说明完
成该订购单所应付出的总金额数
?查询要求:列出每个职工经手的具有最高总金额
的订购单信息
78
列出每个职工经手的具有最高总金额的订购单信息
SELECT 职工号,供应商号,订购单号,订购日期,MAX(总金额 )
FROM 订购单
GROUP BY 职工号
SELECT *
FROM 订购单 outa
WHERE 总金额 = (SELECT MAX(总金额 )
FROM 订购单 innera
WHERE outa.职工号 = innera.职工号 )
结果是:
E7 S4 OR76 2002-05-25 7250.00
E6 S6 OR77 2002-06-29 6000.00
E3 S7 OR67 2002-06-23 35000.00
E1 S6 OR80 2002-07-29 25600.00
79
使用 EXISTS的嵌套查询
?在嵌套查询中还可以使用 [NOT] EXISTS,
具体形式是:
[NOT] EXISTS (子查询 )
?EXISTS或 NOT EXISTS是用来检查在子查
询中是否有结果返回 ( 即存在元组或不存
在元组 ) 。
80
检索那些仓库中还没有职工的仓库的信息。
SELECT * FROM 仓库 WHERE NOT EXISTS
(SELECT * FROM 职工
WHERE 仓库号 = 仓库,仓库号 )
SELECT * FROM 仓库 WHERE 仓库号 NOT IN
(SELECT 仓库号 FROM 职工 )
等价于
结果是:
WH4 武汉 400
81
检索那些仓库中至少已经有一个职工的仓库的信息
SELECT * FROM 仓库 WHERE EXISTS
(SELECT * FROM 职工
WHERE 仓库号 = 仓库,仓库号 )
等价于
SELECT * FROM 仓库 WHERE 仓库号 IN
(SELECT 仓库号 FROM 职工 )
结果是:
WH1 北京 370
WH2 上海 500
WH3 广州 200
82
注意:
?[NOT] EXISTS只是判断子查询中是否有或
没有结果返回, 它本身并没有任何运算或
比较 。
?[NOT] EXISTS实际是一种内, 外层互相关
的嵌套查询, 只有在内层引用了外层的值,
这种查询才有意义 。
83
分组及计算查询
?SQL语言不仅可以从数据库中查询原始信息,
而且还可以直接对查询结果进行计算和汇总。
?SQL语言支持分组的计算和汇总。
?用于计算检索的函数主要有:
?COUNT——计数
? SUM——求和
?AVG——计算平均值
?MAX——求最大值
?MIN——求最小值
84
找出供应商所在地的数目
SELECT COUNT (DISTINCT 地址 )
FROM 供应商
结果为 3
85
求支付的工资总数
SELECT SUM(工资 ) FROM 职工
结果是,6160
86
求在“上海”仓库工作的职工的最高工资

SELECT MAX(工资 ) FROM 职工
WHERE 仓库号 IN
(SELECT 仓库号 FROM 仓库
WHERE 城市 =?上海’ )
结果是,1250
87
求每个仓库的职工的平均工资
SELECT 仓库号,AVG(工资 )
FROM 职工
GROUP BY 仓库号
结果是:
WH1 1230
WH2 1235
WH3 1230
88
求至少有两个职工的每个仓库的平均工资
SELECT 仓库号,COUNT(*),AVG(工资 )
FROM 职工
GROUP BY 仓库号
HAVING COUNT(*) >= 2
结果是:
WH1 2 1230
WH2 2 1235
89
COMPUTE子句
?GROUP BY子句能完成汇总,但是却不能显
示细节。
?利用 COMPUTE子句,汇总结果是附加在细
节之后显示的,这样用户既能看到细节,又
能看到汇总行。
90
COMPUTE子句的格式
COMPUTE <函数名 >(<列名 >)[,<函数名 >(<列名 >)… ] [BY <列名 >[,<列名 >… ]]
? 这里 <函数名 >只能是用于 SELECT计算查询的函数 SUM,AVG,MIN、
MAX和 COUNT等。
? COMPUTE子句中的 BY子句是用来说明分组的,如果在 COMPUTE子句
中不使用 BY子句,则是对整个表进行汇总。
? 这里使用 BY子句,也必须使用 ORDER BY子句,BY子句指出的列必须和
ORDER BY子句指出的列顺序相同,但 BY子句的列数可以少于 ORDER
BY子句的列数。
91
列出职工全部记录并计算各仓库的平均工资和工资小
计,最后给出全体职工的平均工资和工资总和
SELECT 仓库号,职工号,工资 FROM 职工
ORDER BY 仓库号
COMPUTE AVG(工资 ),SUM(工资 ) BY 仓库号
COMPUTE AVG(工资 ),SUM(工资 )
结果是:
WH1 E3 1210
WH1 E7 1250
Avg sum
1230 2460
WH2 E1 1220
WH2 E4 1250
Avg sum
1235 2470
WH3 E6 1230
Avg sum
1230 1230
Avg sum
1232 6160
92
列出职工全部记录并计算全体职工的平均工资和工资总和
SELECT 仓库号,职工号,工资
FROM 职工
COMPUTE AVG(工资 ),SUM(工资 )
结果是:
WH2 E1 1220
WH1 E3 1210
WH2 E4 1250
WH3 E6 1230
WH1 E7 1250
Avg sum
1232 6160
93
视图
仓库号 城市 面积 仓库号 职工号 工资
仓库号 城市 职工号 工资仓库号 面积
基本表
视图
94
定义视图的命令
视图是根据对基本表的查询定义的,
其命令格式如下:
CREATE VIEW <视图名 > AS <SELECT-查询块 >
?从单个表派生出的视图
?从多个表派生出的视图
?视图中的虚列
95
定义视图的例,CREATE VIEW e_w ASSELECT 职工号, 仓库号
FROM 职工
CREATE VIEW v_bj AS
SELECT 仓库号, 面积
FROM 仓库
WHERE 城市 = '北京 '
基于视图进行查询:
SELECT * FROM e_w
96
定义视图的例子:
CREATE VIEW v_sample AS
SELECT 供应商名 FROM 供应商
WHERE 地址 = '北京 ' AND 供应商号 IN
(SELECT 供应商号 FROM 订购单 WHERE 职工号 IN
(SELECT 职工号 FROM 职工 WHERE 仓库号 IN
(SELECT 仓库号 FROM 仓库
WHERE 城市 = '北京 ')))
基于视图的查询,
SELECT * FROM v_sample
97
定义视图的例子:
CREATE VIEW v_emp AS
SELECT 职工号,工资,城市
FROM 职工,仓库
WHERE 职工,仓库号 = 仓库,仓库号 ;
职工号 工 资 城 市
E1 1 2 2 0 上海
E3 1 2 1 0 北京
E4 1 2 5 0 上海
E6 1 2 3 0 广州
E7 1 2 5 0 北京
对用户就好象有一个表:
98
定义视图的例子:
CREATE VIEW v_sal(职工号,月工资,年工资 ) AS
SELECT 职工号,工资,工资 *12 FROM 职工
查询视图 v_sal:
SELECT * FROM v_sal
结果:
E1 1220 14640
E3 1210 14520
E4 1250 15000
E6 1230 14760
E7 1250 15000
99
视图的删除
命令格式是:
DROP VIEW <视图名 >
100
SQL的数据操作功能
?插入功能
?更新功能
?删除功能
101
插入操作
?SQL的插入语句是 INSERT。
?插入一个元组
INSERT INTO <表名 >[(<列名 >[,<列名 >… ])]
VALUES(<表达式 >[,<表达式 >…… ])
?插入一个查询结果
INSERT INTO <表名 >[(<列名 >[,<列名 >… ])] <SELECT查询 >
102
插入操作举例
?插入一个完整的元组
INSERT INTO 订购单 VALUES('E7','S4','OR76','05-25-2002')
?插入一个不完整的元组
INSERT INTO 订购单 (职工号,订购单号 )VALUES('E7','OR76')
?插入一个查询结果
INSERT INTO 订购单备份 SELECT * FROM 订购单
103
更新操作
?SQL的更新语句是 UPDATE。
UPDATE <表名 > SET <列名 > = <表达式 > [,<列名 > = <表达式 >…]
[[FROM <表名 >] WHERE <逻辑表达式 >]
?UPDATE更新满足“逻辑表达式”条件的记录;
?一次可以更新多个属性的值;
?更新的条件可以与其他的表相关(使用 FROM指定);
?如果没有指定更新条件则更新表中的全部记录。
104
更新操作举例
?给 WH1仓库的职工提高 10%的工资
UPDATE 职工 SET 工资 = 工资 *1.10 WHERE 仓库号 = 'WH1'
?给所有职工增加 10%的工资
UPDATE 职工 SET 工资 = 工资 *1.10
?给“武汉”仓库的职工提高 10%的工资
UPDATE 职工 SET 工资 = 工资 *1.10
FROM 仓库
WHERE 仓库,仓库号 = 职工,仓库号 AND 城市 ='武汉 '
105
删除操作
?SQL的删除语句是 DELETE。
DELETE FROM <表名 >
[[FROM <表名 >] WHERE <逻辑表达式 >]
?DELETE命令从指定的表中删除满足“逻辑表达式”条件的元
组;
?如果没有指定删除条件则删除表中的全部元组,所以在使用该
命令时要格外小心;
?删除的条件可以与其他的表相关(使用可选的 FROM指定);
?DELETE命令只删除元组,它不删除表或表结构。
106
删除操作举例
?删除仓库关系中仓库号值是 WH2的元组
DELETE FROM 仓库 WHERE 仓库号 = 'WH2'
?删除所在城市是上海的仓库的所有职工元组
DELETE FROM 职工
FROM 仓库 WHERE 仓库,仓库号 =职工,仓库号
AND 城市 ='上海 '
107
几点注意
?在执行插入、更新和删除操作时可能会受到关系完整性的
约束,这种约束可以保证数据库中的数据是正确的。
?虽然视图可以像基本表一样进行各种查询,但是插入、更
新和删除操作在视图上却有一定限制。因为视图是由基本
表导出的,对视图的任何操作最后都落实在基本表上,这
些操作不能违背定义在表上的完整性约束。
?可以利用游标( Cursor)对表进行删除和更新操作,这部
分内容将在稍后介绍。
108
SQL的数据控制功能
?SQL的数据控制功能主要是指对数据库中
数据的安全控制和管理,即对数据的安全
提供保护,这主要表现在对数据使用的授
权( GRANT)和收回授权( REVOKE)。
每个用户对自己拥有的资源可以有任意的
操作权限,同时也可以把其中的一部分权
限授予他人。这一部分属于数据库安全性
的内容,将在 7.3节进行介绍。
109
SQL的宿主使用
?SQL不仅可以作为独立的数据语言直接以
交互的方式使用; SQL还可以作为子语言
嵌入在宿主语言中使用,这里所说的宿主
语言就是指我们常见的高级程序设计语言,
如 C语言等。
110
把 SQL嵌入到宿主语言中使用必须要解决以
下三个方面的问题:
?嵌入识别问题, 宿主语言的编译程序不能识别
SQL语句,所以首要的问题就是要解决如何区分
宿主语言的语句和 SQL语句;
?宿主语言与 SQL语言的数据交互问题, SQL语
句的查询结果必须能够交给宿主语言处理,宿主
语言的数据也要能够交给 SQL语句使用;
?宿主语言的单记录与 SQL的多记录的问题,
宿主语言一般一次处理一条记录,而 SQL常常处
理的是记录(元组)的集合,这个矛盾必须解决。
111
如何解决嵌入识别问题?
?为了区分主语言和 SQL语句,为 SQL语句加
一个识别前缀,常用前缀格式是:
EXEC SQL
?比如:
EXEC SQL INSERT INTO 职工
VALUES('WH8','E20',1560)
?计算机的编译系统如何识别这些前缀?
112
预编译技术
?在编译之前首先将 SQL语句转换为主语言的
合法函数调用或合法语句,这个过程称为
预编译。
113
嵌入了 SQL的应用程序的执行过程
114
?INCLUDE SQLCA
?如,sqlca.sqlcode
?什么是主变量?
如何解决宿主语言和 SQL语言的数据交换问题?
设立数据通讯区、引入主变量的概念
115
主变量的说明格式
BEGIN DECLARE SECTION

主变量说明

END DECLARE SECTION
116
主变量说明的例:
EXEC SQL BEGIN DECLARE SECTION ;
char whnumb[5]
char city[12]
int wh_area
EXEC SQL END DECLARE SECTION;
117
使用主变量的例子:
UPDATE 仓库
SET 面积 =,wh_area
WHERE 仓库号 =,whnumb ;
118
Cursor
?DECLARE CURSOR
?OPEN
?FETCH
?CLOSE
?DEALLOCATE
为了解决宿主语言一次只能处理一条记
录,而 SQL语言一次处理多条记录的矛盾,
引入了 Cursor的概念。相关的语句有:
119
DECLARE CURSOR语句的格式是:
DECLARE <游标名 > [INSENSITIVE] [SCROLL] CURSOR
FOR <SELECT-查询块 >
[FOR {READ ONLY|UPDATE [OF 〈 列名 〉 [,〈 列名 〉 … ]]}]
?INSENSITIVE说明用数据的临时拷贝来定义游标,所有对游标的
请求都反映在这个临时表上,因此这时的游标实际上是不允许修
改的;
?SCROLL说明可以用所有的方法来存取数据,允许删除和更新
(假定没有使用 INSENSITIVE选项);
?FOR READ ONLY或 FOR UPDATE说明游标为只读的或可修改的。
?<SELECT-查询块 >定义一个游标(文件),它的内容是 <SELECT-
查询块 >的查询结果(多个记录组成的临时表)。
120
OPEN语句的格式是:
OPEN <游标名 >
该语句的功能是打开或启动指出的游标, 该游标名是用
DECLARE CURSOR语句已经定义好的 。 执行该语句意味着执
行在 DECLARE CURSOR语句中定义的 SELECT查询, 并使游
标指针指向查询结果的第一条记录 。 。
121
从游标中读记录
FETCH
[[ NEXT | PRIOR | FIRST | LAST | ABSOLUTE n | RELATIVE n ] FROM ]
<游标名 >
[INTO,<主变量 1>,:<主变量 2>… ]
该语句的功能是取出游标的当前记录并送入主变量,同时使游标指
针指向下一条记录( NEXT,或根据选项指向某条记录)。这里的游标必
须是已经说明并打开了的,INTO后的主变量要与在 DECLARE CURSOR
中 SELECT的字段相对应。
122
关闭游标
CLOSE <游标名 >
123
释放游标
DEALLOCATE <游标名 >
?该命令的功能是删除由 DECLARE说明的游标。
该命令不同于 CLOSE命令,CLOSE命令只是关闭
游标,需要时还可以重新打开;而
DEALLOCATE命令则要释放和删除与游标有关
的所有数据结构和定义。
124
理解游标
?与程序设计语言中的文件相对照:
?DECLARE CURSOR相当于说明了一个文件;
?OPEN相当于打开文件;
?FETCH相当于读一条记录;
?CLOSE相当于关闭文件;
?DEALLOCATE语句相当于删除文件。
125
使用游标的一个 C语言程序段

EXEC SQL BEGIN DECLARE SECTION
char whnumb[5]
char city[12]
int wh_area
EXEC SQL END DECLARE SECTION

EXEC SQL DECLARE c1 CURSOR FOR
SELECT 仓库号,城市,面积
FROM 仓库
WHERE 面积 =,wh_area
EXEC SQL OPEN c1
while ( SQLCA.sqlcode <> 100 )
{
EXEC SQL FETCH c1 INTO,whnumb,:city,:wh_area

}
EXEC SQL CLOSE c1

126
利用游标进行删除和更新操作
?在 T-SQL中,CURSOR不仅仅可以用来浏
览查询结果,还可以用 UPDATE语句修改
CURSOR对应的当前行或用 DELETE命令
删除对应的当前行。
127
使用游标的 UPDATE命令
UPDATE <表名 >
SET <列名 >={<表达式 >|NULL}
[,<列名 >={<表达式 >|NULL}… ]
WHERE CURRENT OF <游标名 >
128
使用游标的 DELETE命令
DELETE FROM <表名 >
WHERE CURRENT OF <游标名 >
129
动态 SQL
?动态 SQL语句的划分
?动态定义功能
?动态操作功能
?动态查询功能
?举例
130
动态 SQL语句的划分
?没有参数, 没有返回结果的 SQL语句, 这类语句
主要是建立数据库对象的语句, 如动态生成的
CREATE TABLE语句;
?有参数, 但没有返回结果的 SQL语句, 这类语句
主要是完成数据库操作的语句, 如动态生成的
INSERT,UPDATE和 DELETE语句;
?有参数, 有返回结果的 SQL语句, 这类语句主要
是对数据库进行动态查询的语句, 也称作动态游
标 ( DYNAMIC CURSOR) 语句 。
131
动态定义功能
?一般格式是:
EXECUTE IMMEDIATE SQLStatement
?其中 SQLStatement是构成合法 SQL语句的字
符串(一般应该是变量)。
132
动态操作功能
?这种格式的动态 SQL语句实际包含了两条语句,
第一条是准备 SQL的语句:
PREPARE SQLSA FROM SQLStatement
?第二条是执行 SQLSA中准备好的 SQL语句:
EXECUTE SQLSA USING {ParameterList}
?其中:
?SQLSA是类似于 SQLCA的系统对象变量
?SQLStatement含有合法 SQL语句的字符串
?ParameterList传递参数的主变量表
133
动态查询功能
?一般格式包括:
?说明动态游标的语句
DECLARE Cursor DYNAMIC CURSOR FOR SQLSA
?为动态游标准备 SQL语句
PREPARE SQLSA FROM SQLStatement
?打开动态游标的语句
OPEN DYNAMIC Cursor {USING ParameterList}
?从游标读记录的语句
FETCH Cursor INTO HostVariableList
?关闭游标的语句
CLOSE Cursor
134
【 本章小节 】
?比较详细的介绍了关系数据库标准语言 SQL
的主要内容,其中包括 SQL语句的查询功能、
定义功能和操作功能,还介绍了视图,SQL
语句的宿主使用方式、游标、动态 SQL语句
和动态游标等内容。掌握和学好 SQL可以说
是学好和用好关系数据库的基础。