1
第三章 SQL 语言基础
SQL概述
SQL (Structured query Language,结构化查询
语言 ),功能包括查询、操纵、定义、控制。
功能丰富、语言简洁、使用灵活,倍受欢迎。
1974年由 Boyce,Chamberlin提出,1975年在 IBM
公司的 System R上首次实现。原型称为
SEQUEL(Structured English QUEry Language),
1986年 ANSI SQL-86标准,是第一个 SQL 标准。
1987年成为国际标准。
1992年 SQL-92标准(简称 SQL2)。
2
1999年 SQL-99标准(简称 SQL3)。 增加了对对象关
系模型的支持。目前仅部分实现。
最流行的国际标准数据库语言。
主要特点,
SQL是非结构化的语言,使用 SQL 查询数据库时,
只需要告诉它做什么而不用告诉它如何去做。
SQL 本身不提供任何程序流程控制结构,而是通过
PL/SQL提供 SQL语言的过程化功能
SQL提供相对固定的数据类型,一般不需要扩展
SQL本身十分灵活,方便易学。
3
标准 SQL只包含 9种语句,
?数据查询,select
?数据定义, create,drop,alter
?数据操纵, insert,update,
delete
?数据控制, grant,revoke
4
数据定义语言( DDL),用于定义数据结构
数据操纵语言( DML),用于检索和修改数
据结构
数据控制语言( DCL),用于规定数据库用
户的各种权限
数据库事务处理,用来保证数据库的完整性
SQL语言分类
5
SQL语言分类
数据定义语言( DDL),用于定义数据结

能使用户完成下列任务
? 创建数据库对象
? 删除数据库对象
? 更改数据库对象
6
常用的 DDL语句包括,
Create Table:创建数据库表
Create Index:创建数据库表的索引
Drop Table:删除数据库表
Drop Index:删除数据库表的索引
Truncate,删除表中所有行
Alter Table,增加表列,重定义表列,更改
存储分配
Alter Table ADD CONSTRAINT,在已有的表上
增加约束
7
数据操纵语言 (DML),允许用户对数据库
中的数据进行 Insert,Update,Delete和
Select等操作
常用 DML语句包括,
Insert, 增加数据行到表
Delete,从表中删除数据行
Update,更改表中数据
Select,从表中或视图中检索数据行
8
数据控制语言( DCL),用于规定数据库
用户的各种权限
常用的数据控制语句包括,
GRANT,将权限或角色授予用户或其它角

REVOKE,从用户或数据库角色回收权限
Set Role,禁止或允许一个角色
9
数据库事务控制,用来保证数据库的完整

常用的事务处理语句包括,
COMMIT WORK,把当前事务所作的更改永
久化(写入磁盘)
ROLLBACK:作废上次提交以来的所有更改
10
事务:指作为单个逻辑工作单元执行的
一系列操作,而这些逻辑工作单元需要
具有原子性,一致性,隔离性和持久性
四个属性。
原子性:指事务必须是原子工作单元,
即对于事务所进行数据修改,要么全都
执行,要么全都不执行
11
一致性:指事务在完成时,必须使所有
的数据都保持一致性状态,而且在相关
数据库中,所有规则都必须应用于事务
的修改,以保持所有数据的完整性。事
务结束时,所有的内部数据结构都必须
是正确的。
12
隔离性:指由并发事务所做的修改必须与
任何其他并发事务所做的修改相隔离。事
务查看数据时数据所处的状态,要么是被
另一并发事务修改之前的状态,要么是被
另一事务修改之后的状态,即事务不会查
看正在由另一个并发事务正在修改的数据。
持久性:指事务完成之后,它对于系统的
影响是永久性的,即使出现系统故障也是
如此。
13
SQL语句的基本语法
基本语法如下,
每条 SQL语句必须以分号结束
每条 SQL语句可以单独写成一行,也可以
分成若干行
SQL语句对大小写不敏感,对于 SQL语句
的关键字(如 Insert等),表名,列名
等,可以大小写混合;但对列的内容则
是大小写敏感的。
14
对象命名约定
SQL Server用三段式名字标识对象,
<数据库名 >.<所有者名 >.<对象名 >
前两者可以省略,系统自动有一个默认值。数据
库名的默认值是当前数据库,所有者名的默认
值是数据库的所有者( dbo)
例如:在 pubs数据库中的 authors表的所有者是
dbo,它可以在多个数据库中按如下方法引用:
pubs.dbo.authors
Pubs.authors
15
别名:使用别名的主要目的是增加
select语句的可读性。可使用如下语句
指派数据表的别名,
数据表名称 as 数据表别名
16
例如,use sample
Select e.员工编号,e.员工姓名
From 员工数据表 as e
注意:如果为数据表指定了别名,则在相应的 T-
SQL语句中,对该数据表的所有显式引用都必
须使用别名,而不能使用数据表名。例如,
Select 员工数据表,员工编号,e.员工姓名
From 员工数据表 as e
17
SELECT 语句
数据检索是数据库中最频繁执行的活动
在 SQL 中, 使用 SELECT 语句可以在需
要的表单中检索数据
在进行检索之前, 必须知道需要的数据
存储在哪里
SELECT 语句可以由多个查询子句组成
18
SELECT 语句
SELECT 语句可用于检索,
? 全部的行和列
? 全部的行和特定的列
? 限定范围的行
? 与一组值匹配的行
? 根据未知值检索的行
? 隐藏有重复值的行
? 根据多个搜索条件检索的行
19
SELECT 语句
Select语句的基本结构如下,
SELECT [ALL | DISTINCT] select_list
[INTO [new_table_name]]
FROM {table_name | view_name}
[[,{table_name2 | view_name2}
[…,,{table_name16 |
view_name16} ] ]
[WHERE search_conditions]
[GROUP BY group_by_list]
[HAVING search_conditions]
[ORDER BY order_list [ASC|DESC]]
20
SELECT 子 句
SELECT 子句指定需要通过查询返回的表的列 。
其语法如下,
SELECT [ ALL | DISTINCT ]
[ TOP n]
<select_list>
各参数说明如下,
其中,select_list表示需要检索的字段的列表,
字段名称之间用逗号分隔。这个列表中既可以
包含数据源表或视图中的字段名称,还可以包
含其它表达式。如用 *,则系统将返回数据表
中的所有字段。
21
ALL,指明查询结果中可以显示值相同的列
ALL 是系统默认的
DISTINCT,指明查询结果中如果有值相同的
列, 则只显示其中的一列 。 对 DISTINCT 选项
来说, Null 值被认为是相同的值
TOP n [PERCENT],指定返回查询结果的前 n
行数据, 如果 PERCENT 关键字指定的话, 则返
回查询结果的前百分之 n 行数据 。
22
例如,
例, 查询所有产品的编号名称和成本
select p_id,p_name,cost
from products
运行结果如下
p_id p_name cost
-------- -------------------- ------
10030001 路由器 20000.0000
10030002 网卡 100.0000
…… 因数据太多故省略之
23
例, 查询数据库表的全部列
select * from employee
运行结果如下
emp_id e_name sex birthday job_level dept_id hire_date e_wage
10010001 张三 1 1968-02-14 00:00:00.000 1 1001 1996-08-02 00:00:00.000 8000.0000
24
例, 查询产品的编号, 名称, 库存数量和成本,
并计算每种产品的总成本价值
select p_id,p_name,quantity,cost,
cost*quantity as sum_cost
from products
运行结果如下
p_id p_name quantity cost sum_cost
10030001 路由器 1000 20000.0000 20000000.0000
25
INTO 子句
INTO 子句用于把查询结果存放到一个新
建的表中 。 SELECT...INTO 句式不能与
COMPUTE 子句一起使用 。 其语法如下
INTO new_table
参数 new_table 指定了新建的表的名称,
新表的列由 SELECT 子句中指定的列构成 。
新表中的数据行是由 WHERE 子句指定的 。
但如果 SELECT 子句中指定了计算列, 在
新表中对应的列则不是计算列, 而是一
个实际存储在表中的列, 其中的数据由
执行 SELECT...INTO 语句时计算得出 。
26
FROM 子句
FROM 子句指定需要进行数据查询的表只
要 SELECT 子句中有要查询的列就必
须使用 FROM 子句其语法如下
FROM {<table_source>} [,...n]
table_source,指明 SELECT 语句要用到
的表, 视图等数据源, 该列表中的数据
表名和视图名之间使用逗号分隔。
27
From子句还可以指定数据表或视图之间联
接的类型,这些类型将决定于 on子句中指
定的联接条件。例如,
Select 员工数据表,员工编号,项目数据
表,项目名称
From 员工数据表 join on
(员工数据表,员工编号=项目数据表,负责
人 )
28
T-SQL可以支持在 from子句中指定除了数
据表或视图以外的其他对象,例如查询
结果集构成的派生表。这些派生表实际
上是 from 子句中 select语句的查询结果
集,这些结果集构成了外层 select语句
查询时所用的数据表。
29
例如,
Select Emp.员工编号,emp.员工姓名,sp.部门名

From 员工数据表 as emp,
(select 部门数据表,部门编号,部门数据表,部门名

From 部门数据表
Where 部门数据表,部门编号 >2) as sp
Where emp.部门编号= sp.部门编号
首先使用 select语句检索高级部门,并用别名 sp表示
该派生表,然后从员工数据表和 sp派生表中检索数
据。
30
Where 子句
Where 子句指定数据检索的条件, 以限制返回的
数据行 。
Where 子句中的查询条件
比较运算符,<,<=,>,>=,=、
>,!=,!<,!>
范围说明,
Between A and B,Not Between A and B
可选值列表,IN,NOT IN
模式匹配,LIKE,NOT LIKE
是否空值,IS NULL,IS NOT NULL
上述条件的逻辑组合,AND,OR,NOT
31
比较查询条件,text,ntext和 image数
据类型不能与比较运算符组合成查询条
件。
列表查询条件,in 关键字在大多数情况
下应用于嵌套查询(又称为子查询)中,
通常首先使用 select语句选定一个范围,
然后将选定的范围作为 in关键字的符号
条件的列表,从而得出最终的结果集。
32
模式查询条件,Like,Not Like
通配符
? * —— 匹配任意字符串
?? —— 匹配任意一个字符
大小写敏感
33
Like关键字中的通配符及其含义
通配

含义
% 由 0个或更多字符组成的任意字符串
_ 任意单个字符
[] 用于指定范围,例如 [a-f],表示 a到
f范围内的任何单个字符
[^] 表示指定范围,例如 [^a-f],表示 a
到 f范围以外的任何单个字符
34
Like关键字举例
like格式 检索范围
Like ‘Mc%’ 以 Mc开头的所有字符串
Like ‘%inger’ 以字母 inger结尾的所有字符串
Like ‘_heryl’ 以字母 heryl结尾的所有 6个字母
的名称
Like ‘[M-Z]inger’ 以 inger结尾、以从 M到 Z的任何单
个字母开头的所有字符串
Like ‘M[^c]%’ 以 M开头,且第二个字母不是 c的
所有字符串
Like ‘%en% ’ 在任何位置包含字母 en的所有字
符串
35
空值判断查询条件,null值表示字段的
数据值未知或不可用,它并不表示零
(数字值或二进制值)、零长度的字符
串或空白(字符值)
36
例如
例, 查询工资介于 2000 元和 3000 元之间的员工姓名
select e_name
from employee
where e_wage between 2000 and 3000
运行结果如下
e_name
--------------------
王二
伍将
(2 row(s) affected)
37
例, 列出工资大于 7000 的员工所属的部门编号
select distinct dept_id
from employee
where e_wage > 7000
运行结果如下
dept_id
-------
1001 1005
(2 row(s) affected)
38
例, 查询在编号为 1001 和 1002 的部门中
工作的员工姓名
select e_name
from employee
where dept_id in (’ 1001’,’ 1002’ )
运行结果如下
e_name
--------------------
张三
李四
39
例, 查找公司中所有姓王, 且全名为两个字的员工
的姓名, 所在部门编号
select e_name,dept_id
from employee
where e_name like ’ 王 __’ /* 注意这里使用了两个
下划线 _符号
运行结果如下
e_name dept_id
-------------------- -------
王二 1001
王朝 1003
(2 row(s) affected)
40
如果用户要查找的数据中本身就包含了通配符,
如 SQL_Mail,就需要使用转义字符来区分通
配符与实际存在的字符。其格式如下
LIKE 字符匹配串 ESCAPE 转义字符
例, 查找对象名称为 SQL_M 开头, il 结尾,
中间有一个不确定字符的对象
select *
from objects
where object_name like ’ SQL#_M_il’
escape ‘ #’
/* 这里使用了两个下划线 _符号, 前一个下划
线由于有逃逸字符在其前面作标识, 因而被认
为是实际存在的下划线字符 ; 后面一个下划线
没有逃逸字符在其前面作标识, 因此将它作为
通配符 */
41
使用 []来将通配符指定为普通字符。
例如,
Select * from object
Where column1 like ‘%54[%]%’
将返回所有包含 54%的字符串
42
GROUP BY 子句
GROUP BY 子句指定查询结果的分组条件 。 其语
法如下,
GROUP BY [ALL] group_by_expression [,...n]
[ WITH { CUBE | ROLLUP } ]
各参数说明如下,
group_by_expression,指明分组条件
group_by_expression 通常是一个列名, 但不能
是列的别名 。 数据类型为 TEXT,NTEXT,IMAGE
或 BIT 类型的列不能作为分组条件
ALL,返回所有可能的查询结果组合, 即使此组
合中没有任何满足 WHERE 子句的数据 。 分组的统
计列如果不满足查询条件, 则将由 NULL 值构成
其数据 。 ALL 选项不能与 CUBE或 ROLLUP 选项同
时使用
43
CUBE,除了返回由 GROUP BY 子句指定的列外,
还返回按组统计的行 。 返回的结果先按分
组的第一个条件列排序显示, 再按第二个条件列
排序显示, 以此类推 。 统计行包括了 GROUP
BY 子句指定的列的各种组合的数据统计
ROLLUP,与 CUBE 不同的是, 此选项对 GROUP
BY 子句中的列顺序敏感, 它只返回第一个分
组条件指定的列的统计行, 改变列的顺序会使
返回的结果的行数发生变化 。
44
例如,
例, 查询工作级别为 2 的员工姓名, 查询结
果按部门分组
select e_name,dept_id
from employee
where job_level = '2'
group by dept_id,e_name
运行结果如下
e_name dept_id
-------------------- -------
李四 1001
张龙 1002
王朝 1003
45
CUBE,除了返回由 GROUP
BY 子句指定的列外, 还
返回按组统计的行 。 返回
的结果先按分组的第一个
条件列排序显示, 再按第
二个条件列排序显示, 以
此类推 。 统计行包括了
GROUP BY 子句指定的列
的各种组合的数据统计
Select 所属部门,性别,
AVG(工资 ) FROM 员工数
据表
Group by 所属部门,性别
With cube
所属部

性别 平均工资
项目部 男 2000
项目部 女 3000
项目部 null 2500项目部全体员工的平
均工资
检验部 男 1750
检验部 女 1000
检验部 null 1500检验部全体员工的平
均工资
录入部 男 1000
录入部 null 1000
办公室 女 3000
办公室 null 3000
null null 1928所有员工的平均工资
null 男 1625所有男性的平均工资
null 女 2333所有女性的平均工资
46
ROLLUP,与 CUBE 不同
的是, 此选项对 GROUP
BY 子句中的列顺序敏
感, 它只返回第一个分
组条件指定的列的统计
行, 改变列的顺序会使
返回的结果的行数发生
变化 。
Select 所属部门,性
别,AVG(工资 ) FROM
员工数据表
Group by 所属部门,性别
With rollup
所属部门 性别 平均工资
项目部 男 2000
项目部 女 3000
项目部 null 2500项目部全体员工的平
均工资
检验部 男 1750
检验部 女 1000
检验部 null 1500检验部全体员工的平
均工资
录入部 男 1000
录入部 null 1000
办公室 女 3000
办公室 null 3000
null null 1928所有员工的平均工资
null 男 1625
null 女 2333
47
若希望在查询结果总仅包
含按照性别分组后取得的
平均值,则需要将 group
by子句中的, 所属部门,
和, 性别, 字段的位置调
换。
Select 所属部门,性别,
AVG(工资 ) FROM 员工数据

Group by 性别,所属部门
With rollup
所属部

性别 平均工资
项目部 男 2000
检验部 男 1750
录入部 男 l 1000
null 男 1625所有男性的平均工资
项目部 女 1000
检验部 女 l 1500
录入部 女 1000
null 女 2333所有女性的平均工资
null null 1928所有员工的平均工资
48
HAVING 子句
HAVING 子句指定分组搜索条件 。 HAVING
子句通常与 GROUP BY 子句一起使用 。
TEXT,NTEXT和 IMAGE 数据类型不能用于
HAVING 子句 。 其语法如下
HAVING <search_condition>
HAVING 子句与 WHERE 子句很相似, 其区
别在于其作用的对象不同 。 WHERE 子句
作用于表和视图, HAVING 子句作用于组
49
例如,
例, 查询有多个员工的工资不低于 6000 的部
门编号
select dept_id,count(*)
from employee
where e_wage >= 6000
group by dept_id
having count(*) > 1
运行结果如下
dept_id
------- -----------
1005 2
1007 3
(2 row(s) affected)
50
ORDER BY 子句
ORDER BY 子句指定查询结果的排序方式 。 其语法如
下,
ORDER BY {order_by_expression [ ASC | DESC ] }
[,...n]
各参数说明如下,
order_by_expression,指定排序的规则
order_by_expression 可以是表或视图的列的名称或
别名, 如果 SELECT语句中没有使用 DISTINCT 选项或
UNION 操作符, 那么 ORDER BY 子句中可以包含
select list 中没有出现的列名或别名 。 ORDER BY
子句中也不能使用 TEXT,NTEXT和 IMAGE 数据类型
ASC,指明查询结果按升序排列这是系统默认值
DESC,指明查询结果按降序排列
51
例如,
例, 查询工作级别为 2的员工姓名, 查询结果
按工资排序
select e_name
from employee
where job_level = ’ 2’
order by e_wage
运行结果如下
e_name
--------------------
王朝
李四
姜上
52
例, 查询由编号 1003的部门生产的产品编号,
名称, 成本, 库存数量, 结果按产品的成本降
序, 库存数量升序排列
select p_id,p_name,cost,quantity
from products
where dept_id = ’ 1003’
order by cost desc,quantity
运行结果如下
p_id p_name cost quantity
-------- -------------------- ------------
10030001 路由器 20000.0000 1000
10030005 中继器 10000.0000 20000
53
例, 查询工资最高的三名员工的姓名和工资
select top 3 e_name,e_wage
from employee
order by e_wage desc
运行结果如下
e_name e_wage
-------------------- ---------------------
张三 8000.0000
大师傅 7500.0000
张龙 7000.0000
(3 row(s) affected)
54
COMPUTE 子句
COMPUTE 子句在查询结果的末尾生成一个汇总数
据行, 其语法如下, COMPUTE
{ { AVG | COUNT | MAX | MIN | SUM }
(expression) } [,...n]
[ BY expression [,...n] ]
各参数说明如下,
AVG | COUNT | MAX | MIN | SUM,以上参数
与对应的函数有相同的含义, 这些函数均会忽略
NULL值且 DISTINCT选项不能在此使用
55
expression,指定需要统计的列的名称, 此列
必须包含于 SELECT列表中, 且不能用别名 。
COMPUTE子句中也不能使用 TEXT,NTEXT和
IMAGE 数据类型
BY expression,在查询结果中生成分类统
计的行 。 如果使用此选项, 则必须同时使用
ORDER BY 子句 。 expression 是对应的 ORDER
BY 子句中的 order_by_expression 的子集或
全集
56
例如,
Select 员工姓名,所属部门,工资
From 员工数据表
Order by 所属部门
Coumpute sum(工资 ) by 所属部门
注意:在加入 by 关键字及其分组字段的同
时必须将这个分组字段同时作为排序条
件,否则查询会出错。
57
? 把一列中的值进行汇总运算,返回单值的函数
? 五个预定义的聚合函数
?平均值,Avg
?总和,Sum
?最小值,Min
?最大值,Max
?计数,Count
? Count(*),Count(Distinct… )
数值
汇总函数
58
汇总函数忽略 Null
?Count,count函数将忽略对象中的空值,而 count(*)
函数则将所有符合条件的记录都计算在内
?Sum,忽略求和对象中的空值
?Avg,忽略求和对象中的空值
?Max / Min,忽略求和对象中的空值
汇总函数 —— Null
59
例如,
例, 查询公司的员工总数
select count(*)
from employee
运行结果如下
21
(1 row(s) affected)
60
例, 查询各部门中的最高工资数额
select dept_id,max(e_wage) as max_wage
/* 使用 as 字符来指定统计列的名称 */
from employee
group by dept_id
运行结果如下
dept_id max_wage
------- ---------------------
1001 8000.0000
1002 7000.0000
1003 4500.0000
61
例, 查询订货量大于库存量的产品名称
select p_name,quantity,sum(o_quantity)
as sum_order
from products,orders
where products.p_id = orders.p_id
group by products.p_id,p_name,quantity
having quantity < sum(o_quantity)
order by products.p_id
运行结果如下
p_name quantity sum_order
-------------------- ----------- -----
光纤 10000 19000
调制解调器 18000 23000
(2 row(s) affected)
62
Select count(*) from 项目数据库
Where 结束日期 <=‘ January 1,2002’
Select count(distinct 负责人 )
From 项目数据库
Where 结束日期 <=‘ January 1,2002’
注意:使用 count 函数可以同时使用可选关键字
distinct来去掉重复值,而使用 count(*)函数
则不可以
63
UNION 子句
UNION 操作符将两个或两个以上的查询结果合
并为一个结果集 。 它与使用连接查询
合并两个表的列是不同的, 使用 UNION 操作符
合并查询结果需要遵循两个基本规则, 列的数
目和顺序在所有查询中必须是一致的 ; 数据类
型必须兼容
其语法如下,
Select 语句
UNION [ALL]
Select 语句
64
注意,
使用 union子句获得的结果集的字段名称与
union运算符 之前的 select语句结果集中的字
段名相同,union运算符之后的 select语句结
果集的字段名将被忽略。
在默认情况下,union运算符将从最终结果集
中删除重复的记录。如果希望最终结果集保留
所有的记录,则必须使用 all关键字。
65
在使用 union运算符时,单独的 select语句中
不能包含其自己的 order by或 coumpute子句
只能在最后一个 select语句的后面使用一个
order by 或 compute 子句,此时,该子句将
适用于最终的组合结果集
若需要对查询结果进行分组以及在分组后对结
果使用 having子句进行过滤,则必须在单独的
select语句中指定 group by和 having子句。
66
例如,
例:查询计算机系的学生或者年龄不大于 19岁的
学生,并按年龄倒排序。
Select * from department where sdept=“计算
机, ;
Union;
Select * from student where sage<=19
order by sage desc
67
联接查询
通过使用联接查询,可以根据各个数据表之间的逻辑关
系从两个或多个数据表中检索数据。
定义数据表之间的关联方式,
1 在数据表中指定用于联接的字段。典型的联接条件是在
一个数据表中指定外键,同时在另一个数据表中指定与
其关联的主键。
2 在 select 语句中指定比较各字段值时要使用的逻辑运算
符。
联接的类型,
内连接
外联接:左向外联接,右向外联接,完整外联接
交叉联接
68
内连接
内联接的格式为,
数据表 1 inner join 数据表 2 on 联接表达式
指定返回两个表中所有匹配的行。
?Inner是缺省的连接方式
例,select * from 员工数据表
Inner join 项目数据表
On 员工数据表,员工编号=项目数据表,负责

69
外联接:左向外联接,右向外联接和完整外联接。
左向外联接的格式为,
数据表 1 left join 数据表 2 on 联接表达式 或
数据表 1 left outer join 数据表 2 on 联接表达式
注意,返回结果集中将包括数据表 1中所有的记录,
而不仅仅是联接字段所匹配的记录。如果数据表 1
的某条记录在数据表 2中没有匹配的记录,则结果
集相应记录的有关数据表 2的所有字段将为空值。
例如,select * from 员工数据表
left join 项目数据表
On 员工数据表,员工编号=项目数据表,负责人
则:检索员工数据表中的所有记录,并将项目数据
表中负责人字段可以匹配的记录输出到结果集。
70
右向外联接的格式为,
数据表 1 right join 数据表 2 on 联接表达式 或
数据表 1 right outer join 数据表 2 on 联接表达式
注意,返回结果集中将包括数据表 2中所有的记录,而
不仅仅是联接字段所匹配的记录。如果数据表 2的某
条记录在数据表 1中没有匹配的记录,则结果集相应
记录的有关数据表 1的所有字段将为空值。
例如,select * from 员工数据表
right join 项目数据表
On 员工数据表,员工编号=项目数据表,负责人
则:检索项目数据表中的所有记录,并将员工数据表
中员工编号字段可以匹配的记录输出到结果集。
71
完整外联接
格式如下,
数据表 1 full join 数据表 2 on 联接表达式
或,
数据表 1 full outer join 数据表 2 on 联接表
达式
结果集将包含两个数据表中的所有记录,当某条
记录在另一个数据表中没有匹配记录时,则将
另一个数据表的选择列表字段指定为空值
72
交叉联接
格式为:数据表 1 cross join 数据表 2
如果在 select语句中没有使用 where子句,则交叉
联接将返回数据表 1和数据表 2中记录的笛卡儿乘
积,即交叉联接返回数据表 1中的所有记录,以及
数据表 1中的每一条记录与数据表 2中的所有记录
的组合。
例如,select * from 员工数据表
Cross join 项目数据表
将返回员工数据表中的所有记录,以及员工数据表
中的每条记录与项目数据表中的所有记录的组合。
73
嵌套查询
嵌套查询是指在一个外层查询中包含有另一个内层
查询。其中,外层查询称为主查询,内层查询称为
子查询。
SQL允许多层嵌套,由内而外地进行分析,子查询
的结果作为主查询的查找条件
可以用多个简单查询来构成复杂查询,以增强 SQL
的查询能力
子查询中一般不使用 Order By 子句,Order By子
句只能对最终查询结果进行排序
74
子查询( Subquery )
包含子查询的格式通常采用如下格式,
?Where 表达式 [not] in ( 子查询)
?Where 表达式 比较运算符 [any|all] 子查询
?Where [not] exists (子查询 )
75
返回单值的子查询,只返回一行一列
主查询与单值子查询之间用比较运算符进行连接
?运算符,>,>=,=,<=,<,<>
例:找出与 95001同龄的学生
Select *
From Student
Where sage = ( Select sage
From Student
Where sno = ‘95001’ )
子查询 —— 单值比较
76
例, 查询订购了产品光纤的公司名称
select f_name from firms
where firm_id in
(select firm_id from orders
where p_id = (select p_id
from products
where p_name = '光纤 '))
order by firm_id
77
例:查询选修‘ C01’ 课程的学生的学号、姓
名。
Select sno,sname
From Student
Where sno IN ( Select sno
From SC
Where cno = ‘C01’ )
子查询 —— In
78
例, 查询有工资超过 7000 的员工的部门名称, 查
询结果按部门编号排序
select d_name from department
where dept_id in
(select dept_id
from employee
where e_wage > 7000)
order by dept_id
79
例,查询选修了 ‘数据库’的学生的学号和姓名
Select sno,sname
From Student
Where sno IN
( Select sno
From SC
Where cno IN
( Select cno
From Course
Where cname = ‘数据库 ’))
子查询 —— In
80
多值比较:多行一列
? 父查询与多值子查询之间的比较需用 All来连接
? 标量值 s比子查询返回集 R中的每个都大时,s>All R
为 True
? All表示所有
? > all,< all,<=all,>=all,<> all
? <> all 等价于 not in
例:找出年龄最小的学生
Select * From Student Where sage < all (
Select sage From Student )
子查询 —— 多值比较 all
81
父查询与多值子查询之间的比较需用 Some/Any来
连接
? 标量值 s比子查询返回集 R中的某一个都大时
?s > Some R为 True 或
?s > Any R为 True
? Some(早期用 Any)表示某一个,只要有一个即返回真
? > some,< some,<=some,>=some,<> some
? = some 等价于 in,<> some 不等价于 not in
子查询 —— 多值比较 Some/Any
82
例:找出不是最小年龄的学生
Select * From student
Where sage > some ( Select sage
From Student )
子查询 —— 多值比较
83
Exists + 子查询用来判断该子查询是否返回元组
当子查询的结果集非空时,Exists为 True
当子查询的结果集为空时,Exists为 False
不关心子查询的具体内容,因此用 Select *
子查询 —— 存在判断 Exists
84
例:列出选修了 C01课程的学生的学号、姓名
Select sno,sname
From Student
Where Exists
( Select *
From SC
Where SC.sno = Student.sno And
cno = ‘C01’)
子查询 —— Exists
85
例:列出没有选 C01课程的学生的学号、姓名
Select sno,sname
From Student
Where Not Exists
( Select *
From SC
Where SC.sno = Student.sno And
cno = ‘C01’)
子查询 —— Not Exists
86
例:列出得过 100分的学生的学号、姓名
Select sno,sname
From Student
Where Exists
( Select *
From SC
Where SC.sno = Student.sno And
grade = 100)
子查询 —— Exists
87
如何提高 select语句的效率
使用 exists关键字检查结果集:不要用
count(*)来检查结果集中是否包含行。
使用标准联接代替嵌套查询:在执行嵌套查询
时,SQL Server将先执行内部的子查询,然后
将查询结果返回给外部查询作为检索的数据源,
最后执行外部的主查询。而在执行包含标准联
接的查询时,SQL Server将要执行的仅仅是一
个查询。
有效避免整表扫描:使用索引;
除了缺失索引外,可能导致整表扫描的另外一种
常见的情况是在 like子句的匹配条件的开始使
用了 %。若在 like子句的匹配条件的开始使用
了 %,那么包含这个 like分句的查询将会调用
完整表扫描。
88
数据插入
? 格式 1,INSERT INTO <表名 > [( <列名 1> [,<列名
2>… ] ) ] VALUES (<值 1> [,<值 2 > … ]) ;
?insert语句把 values后给出的各 值 按排列顺序依次赋
到 表名 后列出的各列。每次只能插入一条记录。
? 例,INSERT INTO student VALUES(95006,‘张三 ’,
‘ 男 ’,21,‘ cs’) ;
? 例,insert into student(sname,sno,sdept)
values(‘章小山 ’,96008,
‘ IS’);
---在 student中添加一条记录,其中列 ssex,sage为空
(null)。
?若表名后不列出列名,则等价于列出了全部列名,必
须在 values后给出全部列值,并按创建表时的列定义
顺序,把这些值赋入相应列中。若某些列暂时没有值,
则给出 null,
89
? 格式 2,INSERT INTO <表名 > [( <列名 1> [,<列名
2>… ] ) ] Select 语句;
?把 select语句查询的结果按顺序插入到对应的列中。
允许一次插入多条记录。
?Select查得的各列值必须与 <表名 >后的各列名在个
数、类型及顺序上一致。
?若 <表名 >后没有 (列名 ),则对该表的所有字段插入。
create table student2(sno char(6) not null,
sname varchar(20),birthdate date,sdept
char(2),phone varchar(15));
?Insert into student2(sno,sname,sdept,
birthdate) select sno,sname,sdept,2001-
sage from student;
90
? 格式,UPDATE <表名 > SET <列名 1>=<表达式 1>
[,<列名 2>=<表达式 2> … ] [WHERE <条件 >];
? Where后的条件与查询语句中的 where条件语法
和作用相同。
? 该语句将指定表中符合 WHERE <条件 >的行中的
指定列赋新值。若没有 where,则对整个表修改。
? 该语句一次可以更新一列或多列;更新一行或
多行 (由 where的选择条件决定 )。
数据修改
91
例:将 95001学生转入 MA系
Update Student
Set sdept = ‘MA’
Where sno = ‘95001’
例:所有学生年龄加 1
Update Student
Set sage = sage + 1
数据修改
92
例:将选修 C05课程的学生的成绩改为该课的
平均成绩
Update SC
Set grade = (Select avg(grade)
From SC
Where cno = ‘C05’)
Where cno = ‘C05’
先计算 avg,再做 Update
93
删除数据
DELETE [FROM] {table_name |
view_name}
[WHERE 子句 ]
? 删除表中符合选择条件的行(一行或多行)。
? 若无 where部分,则删除整个表中全部数据,
但表结构仍存在,即成为空表。
? delete只能整行删除,不能只删一行的部分。
94
删除单个元组
例:删除学号为 95001的学生的选课信息
Delete From SC
Where sno = ‘95001’
删除多个元组
例:删除选课而未参加考试的学生的选课信息
Delete From SC
Where grade is null
删除整个关系中的所有数据
例:删除所有学生的选课信息
Delete From SC
95
注意,
? 数据更新语句只能对单表操作,不能同时对多
表更新。 (从而引起阶段性的数据不一致性 )
? 数据更新语句仅当事务 (transaction)提交
(commit)后才正式生效。也可通过事务回滚
(rollback)来作废。