第四章 sql 操纵功能

129

Upload: chester-tyler

Post on 02-Jan-2016

79 views

Category:

Documents


3 download

DESCRIPTION

第四章 SQL 操纵功能. SQL 数据操纵功能. SQL 数据查询功能 SQL 数据查询基本结构 select 子句 from 子句 where 子句 重复元组的处理 更名运算 元组显示顺序 字符串操作. SQL 数据查询功能 全文检索 关系的连接 分组和聚集函数 空值 派生关系 嵌套子查询 集合操作 递归查询. SQL 数据操纵功能. 插入 删除 更新. SQL 数据查询基本结构. 基本结构 select A 1 , A 2 , … , A n from r 1 , r 2 , … , r m where P - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第四章  SQL 操纵功能
Page 2: 第四章  SQL 操纵功能

SQL 数据操纵功能 SQL 数据查询功能

SQL 数据查询基本结构 select 子句 from 子句 where 子句 重复元组的处理 更名运算 元组显示顺序 字符串操作

SQL 数据查询功能 全文检索 关系的连接 分组和聚集函数 空值 派生关系 嵌套子查询 集合操作 递归查询

Page 3: 第四章  SQL 操纵功能

SQL 数据操纵功能 插入 删除 更新

Page 4: 第四章  SQL 操纵功能

SQL 数据查询基本结构 基本结构

select A1 , A2 , … , An

from r1 , r2 , … , rm

where P

∏A1 , A2 , … , An(p(r1 r2 … rm))

Page 5: 第四章  SQL 操纵功能

SQL 数据查询基本结构

select R.A

from R

where R.B < 10

select R.A

from R, S

where R.B < 10

VSPKKO

RA B

1 2

1 3

SC D

3 4

1 3

Page 6: 第四章  SQL 操纵功能

select 子句 目标列形式

可以为列名, * ,算术表达式,聚集函数 “*” :表示“所有的属性”

给出所有学生的所有信息select *from S

带,, , 的算术表达式给出所有学生的姓名及出生日期select SNAME , 2010- AGEfrom S

Page 7: 第四章  SQL 操纵功能

select 子句 将多个列组合为一列

示例:给出每个老师信息的自然语言描述。

select pname + ’ 老师的工资是’ + salary +

’, 年 龄 是 ’ + age + ’, 职 称是’ + titlefrom professor

输出行的形式类似:“ 李明老师的工资是 1500, 年龄是 45, 职称是教

授”

Page 8: 第四章  SQL 操纵功能

from 子句 from 子句列出查询的对象表 示例

找出选修课程的学生姓名、课程名、成绩

selectSNAME , CNAME, GRADEfrom S , C, SCwhere S.S# = SC.S#

and C.C# = SC.C#

GRADECNAMESNAMECSCS

,,)(

)C(C #.#.#.#. SCSSCS CCCSCSSCSS

Page 9: 第四章  SQL 操纵功能

乱花渐欲迷人眼

写出与 等价的 SQL),(),( CBSBAR

当目标列取自多个表时,需要显式指明来自哪个关系

select *

from R, S

where R.B=S.B

select A, B, C

from R, S

where R.B=S.B

select A, R.B, C

from R, S

where R.B=S.B

Page 10: 第四章  SQL 操纵功能

where 子句 语法成分

比较运算符:、 、、、 = 、

逻辑运算符: and , or , not between :判断表达式的值是否在某范围内

列出工资在 500~800 之间的老师姓名 select PNAME

from PROF

where SAL between 500 and 800 A between a1 and a2 A>=a1 and A<=a2 ?

Page 11: 第四章  SQL 操纵功能

重复元组的处理 语法约束

SQL 缺省为保留重复元组,也可用关键字 all 显式 指 明 。 若 要 去 掉 重 复 元 组 , 可 用 关 键 字distinct 指明

示例 找出所有选修课程的学生

select distinct S#

from SC

A(R) = (select A from R)?

Page 12: 第四章  SQL 操纵功能

重复元组的处理

查询一: 查询二: 查询三:select distinct R.A, S.A

from R, S

where R.B = S.C

select distinct R.A

from R, S

where R.B = S.C

select distinct R.A

from R, S where R.B = S.A

两个表 R(A, B), S(A, C) ,其中 A 是这两个表的主码 , 哪些查询中的 distinct 可以去掉?

Page 13: 第四章  SQL 操纵功能

元组显示顺序 命令

order by 列名 [asc | desc] 示例

按年龄升序列出学生信息,相同年龄学生按姓名降序排列。

select *

from S

order by AGE asc , SNAME desc

Page 14: 第四章  SQL 操纵功能

元组显示顺序

示例:对教工按缴纳所得税的多少排序select fname, sal * 0.2

from faculty

order by 2

示例:按年龄顺序输出学生姓名select sname

from student

order by age

Page 15: 第四章  SQL 操纵功能

更名运算 格式

old_name as new_name

为关系和属性重新命名,可出现在 select和 from 子句中注: as 可选

Page 16: 第四章  SQL 操纵功能

更名运算 属性更名

例:给出所有学生的姓名、性别、出生日期,并按出生日期升序排列

select SNAME ‘ 姓名’ , SEX ‘ 性别’ ,

2007-AGE ‘ 出生日期’from S

order by 出生日期(或者 order by 3)

Page 17: 第四章  SQL 操纵功能

更名运算 关系更名

找出比 s1 学生选修 c1 课程成绩高的学生号

select S2.S#

from SC as S1 , SC as S2

where S1.S# = ‘s1’

and S1.C# = ‘c1’

and S2.C# = ‘c1’

and S1.GRADE < S2.GRADE

#.2 21.2.11#.21#.11#.1 )))()(((SS SSGSGScCScCSsSS SCSC

Page 18: 第四章  SQL 操纵功能

更名运算 找出工资比所在系主任工资高的老师姓名及工资

PROF

P# D# SAL

P1 D1 800

P2 D1 700

DEPT

D# DEAN

D1 P2

select P1.PNAME , P1.SAL

from PROF as P1 , PROF as P2 ,DEPT

where P1.D# = DEPT.D#

and DEPT.DEAN = P2.P#

and P1.SAL > P2.SAL

(PROF)DEPT(PROF) P2P2.P#DEPT.DEANDEPT.D#P1.D#P1

Page 19: 第四章  SQL 操纵功能

字符串操作 命令格式

列名 [not] like ‘ 字符串’找出满足给定匹配条件的字符串

匹配规则 ‘%’ :匹配零个或多个字符 ‘ _’:匹配任意单个字符 [ ] :任何在指定范围内的字符

[a-f] , [abcdef] [^] :任何不在指定范围内的字符

[^ a-f] , [^ abcdef]

Page 20: 第四章  SQL 操纵功能

字符串操作 Escape

定义转义字符,以去掉特殊字符的特定含义,使其被作为普通字符看待

如 escape ‘ \ ‘ ,定义 \ 作为转义字符,则可用 \% 去匹配 % ,用 \ _去匹配_

‘ %a_bx ’

select * from tt

where c1 like ‘x%%xx' escape ‘x'

思考:用什么去匹配 \ ?

Page 21: 第四章  SQL 操纵功能

字符串操作 示例

列出姓名以“张”打头的教师的所有信息 select *

from PROF

where PNAME like ‘ 张 % ‘ 列出名称中含有 3 个以上字符,且倒数第三个是

d ,倒数第二个是 _ 的课程select * from Cwhere CNAME LIKE ‘%_d\ _ _ ‘ escape ‘ \ ‘

Page 22: 第四章  SQL 操纵功能

字符串操作USE NorthwindSELECT LastName, FirstName, NotesFROM EMPLOYEESWHERE Notes Like '%french%'

USE NorthwindSELECT LastName, FirstName, NotesFROM EMPLOYEESWHERE Notes Like '%german%french%'

USE NorthwindSELECT LastName, FirstName, NotesFROM EMPLOYEESWHERE Notes Like '%french%german%'

包含french

包含 french

和german

Page 23: 第四章  SQL 操纵功能

字符串操作在 CNAME 上建有索引 CNAME_idx ,观察下面查询的执行计划,看谁用到了该索引。

A. select * from C where CNAME like '%d'

B. select * from C where CNAME like 'd%'

小巫见大巫Like

全文索引 正则表达式

Page 24: 第四章  SQL 操纵功能

正则表达式 正则表达式( Regular Expression)

记录文本规则的代码 一个用来描述或者匹配一系列符合某个句法规则的

字符串的单个字符串 简单示例

zo* 匹配“ z” 和“ zoo” zo+ 与“ zo” 和“ zoo” 匹配,但与“ z” 不匹配 o{2} 与“ fol” ,” foool” 不匹配,但与“ fool”

匹配 o{2,} 不 匹 配 ” fol” , 匹

配” fool”,”foooooool” z|food 匹配” z” 或” food” (z|f)ood 匹配“ zood” 或” food”

Page 25: 第四章  SQL 操纵功能

常见正则表达式 用户名:

/^[a-z0-9_-]{3,16}$/ 密码:

/^[a-z0-9_-]{6,18}$/ 电子邮箱:

/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/ IP 地址:

/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

HTML 标签:/^<([a-z]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)$/

Page 26: 第四章  SQL 操纵功能

正则表达式: Oracle

函数名 说明

REGEXP_LIKE类似于 LIKE 运算符,但执行正则表达式匹配而不是简单的模式匹配

REGEXP_INSTR在给定字符串中搜索某个正则表达式模式,并返回匹配项的位置

REGEXP_REPLACE

搜索某个正则表达式模式并使用替换字符串替换它

REGEXP_SUBSTR在给定字符串中搜索某个正则表达式模式并返回匹配的子字符串

Page 27: 第四章  SQL 操纵功能

正则表达式: Oracle

ALTER TABLE students

ADD CONSTRAINT stud_ssn_ck

CHECK (REGEXP_LIKE(ssn,

'^([[:digit:]]{3}-[[:digit:]]{2}-[[:digit:]]{4}|[[:digit:]]{9})$'))

REGEXP_SUBSTR(cust_email, '[^@]+')

REGEXP_REPLACE (catalog_url, 'http://([^/]+).*', '\1')

REGEXP_REPLACE('Ellen Hildi Smith’,'(.*) (.*) (.*)', '\3, \1 \2')

Page 28: 第四章  SQL 操纵功能

全文检索

dialogue

Are you kidding?

No, I’m serious.

你是凯丁吗?不,我是史瑞斯。

create index idx1 on film(dialogus)

select * from film where dialogue like ‘%serious%’

Page 29: 第四章  SQL 操纵功能

全文检索

Page 30: 第四章  SQL 操纵功能

全文检索

正文

倒排索引

Page 31: 第四章  SQL 操纵功能

全文检索:创建

create fulltext catalog catalog_name

create fulltext index on table_name [(column_name ]

key index index_nameon catalog_name

key index 指定 table_name 上唯一键索引的名称,最好是聚簇索引

Page 32: 第四章  SQL 操纵功能

全文检索:查询

Contains( 属性列 |* ,查找条件 )

FREETEXT( 属性列 |* ,查找文本 ) 使用 FREETEXT 时,全文查询引擎内部将查找文

本拆分为若干个搜索词,并赋予每个词以不同的加权,然后查找匹配

Page 33: 第四章  SQL 操纵功能

全文检索 示例:全文索引的创建及使用演示

doc(doc_id, title, author, abstract, content)

create unique clustered index doc_idx

on doc(doc_id)

create fulltext catalog doc_fulltext_ catalog

create fulltext index on

doc (title, author, abstract, content)

key index doc_idx

on doc_fulltext_catalog

Page 34: 第四章  SQL 操纵功能

全文检索select*from documentswhere contains (*, 'database and

dataspace')

select*from documentswhere contains (author, 'Jim Gray and

not Jeff Ullman')

Page 35: 第四章  SQL 操纵功能

全文检索select*from documentswhere contains ((title, abstract), 'graph

mining')

select*from documentswhere freetext (content,

' Adaptive Query Processing')数据库查询和信息检索的区别

Page 36: 第四章  SQL 操纵功能

全文检索: SQL Server 2000

sp_fulltext_catalog 创建和除去全文目录,然后启动和停止目录的索引

操作。可为每个数据库创建多个全文目录

sp_fulltext_database 初始化全文索引,或者从当前数据库中删除所有的

全文目录

USE NorthwindEXEC sp_fulltext_database 'enable'

USE NorthwindEXEC sp_fulltext_catalog ’Northwind_FT’,’create’

Page 37: 第四章  SQL 操纵功能

全文检索: SQL Server 2000

sp_fulltext_table 为全文索引对表进行标记或去除标记

sp_fulltext_column 指定表的某个特定列是否参与全文索引

USE NorthwindEXEC sp_fulltext_table 'products', 'create',

'NorthwindFT','PK_Products'

EXEC sp_fulltext_column 'products', 'ProductName', 'add',0

EXEC sp_fulltext_column 'products', 'QuantityPerUnit', 'add',0

Page 38: 第四章  SQL 操纵功能

全文检索: SQL Server 2000

sp_fulltext_catalog 之 start_full 启动 fulltext_catalog_name 的完全填充

USE NorthwindEXEC sp_fulltext_catalog 'NorthwindFT', 'start_full'

SELECT * FROM productsWHERE CONTAINS(*,'boxes')

SELECT * FROM ProductsWHERE CONTAINS(*,'gift and boxes')

SELECT * FROM ProductsWHERE CONTAINS(*,'gift or boxes')

Page 39: 第四章  SQL 操纵功能

全文检索SELECT * FROM productsWHERE CONTAINS(*, 'gift and not boxes')

SELECT * FROM ProductsWHERE CONTAINS(*,' "gift and boxes" ')

SELECT * FROM ProductsWHERE CONTAINS(*,' gift near boxes ')

SELECT * FROM ProductsWHERE CONTAINS(*,' "ch*" ')

Page 40: 第四章  SQL 操纵功能

关系的连接 基本分类

连接成分包括两个输入关系、连接条件、连接类型

连接条件决定两个关系中哪些元组相互匹配,以及连接结果中出现哪些属性

连接类型决定如何处理与连接条件不匹配的元组

Page 41: 第四章  SQL 操纵功能

关系的连接

连接类型 连接条件

inner joinleft outer join

right outer joinfull outer join

on <谓词 >

(R cross join S) as T

两个关系的笛卡儿积

Page 42: 第四章  SQL 操纵功能

关系的连接R S

A B B C1 2 2 32 3 2 53 4 3 6

R inner join S on R.B = S.B

A R.B S.B C

1 2 2 3

1 2 2 5

2 3 3 6

Page 43: 第四章  SQL 操纵功能

R left outer join S on R.B = S.B

A R.B S.B C

1 2 2 3

1 2 2 5

2 3 3 6

3 4 null null

R full outer join S on R.B < S.B

A R.B S.B C

1 2 3 6

2 3 Null null

3 4 Null null

null null 2 3

null null 2 5

Page 44: 第四章  SQL 操纵功能

关系的连接 列出老师的教工号、姓名、工资、所教课程号select P# , PNAME , SAL , C#

from (PROF left outer join PC on PROF.P#=PC.P#)

select P# , PNAME , SAL , C#

from PROF, PC

where PROF.P# = PC.P#

union

select P# , PNAME , SAL , null

from PROF

where P# not in (select P# from PC)

Page 45: 第四章  SQL 操纵功能

空值

AND TRUE FALSE UNKNOWN

TRUE TRUE FALSE UNKNOWN

FALSE FALSE FALSE FALSE

UNKNOWN UNKNOWN FALSE UNKNOWN

OR TRUE FALSE UNKNOWN

TRUE TRUE TRUE TRUE

FALSE TRUE FALSE UNKNOWN

UNKNOWN TRUE UNKNOWN UNKNOWN

Page 46: 第四章  SQL 操纵功能

空值 空值测试

is [not] null测试指定列的值是否为空值

注意事项 除 is [not] null 之外,空值不满足任何查找条件 如果 null参与算术运算,则该算术表达式的值为

null 如果 null参与比较运算,则结果可视为 false 。在

SQL-92 中可看成 unknown表中存在两行 (1, 2, null), (1, 2, null) , select distinct * ?

Page 47: 第四章  SQL 操纵功能

空值 示例

找出成绩值为空的学生号 select S#

from SC

where GRADE is null

不可写为 where GRADE = null

Page 48: 第四章  SQL 操纵功能

空值 isnull

isnull(check_expression, replacement_value)

如 果 check_expression 值 为 空 , 则 返 回replacement_value, 否 则 返 回check_expression

select S#, C#, isnull ( GRADE, 0 )

from SC

Page 49: 第四章  SQL 操纵功能

空值 coalesce

coalesce(expression1, expression2, … ) ,返回第一个不为 null 的 expression

select s#, c#, coalesce(grade, 0)from sc

Page 50: 第四章  SQL 操纵功能

空值 缺省情况下空值是最后输出的。当指定 order by

时,降序情况下首先输出空值,升序情况下最后输出空值 示例:首先由小到大输出非空 sal ,然后是空值

salselect fname, sal

from faculty

order by 2 首先输出空值 sal ,然后由大到小输出非空 sal

select fname, sal

from faculty

order by 2 desc

Page 51: 第四章  SQL 操纵功能

空值 首先输出空值 sal ,然后由小到大输出非空 sal 。

select fname, sal

from (select fname, sal,

case when sal is null

then 0 else 1 as is_null

from faculty) temp_faculty

order by is_null, sal fname sal is_null

bob 1000 1

tom null 0

cat 1200 1

Page 52: 第四章  SQL 操纵功能

聚集函数 聚集函数

将一列中所有的值聚集为单个值 平均值: avg 最小值: min 最大值: max 总和: sum 记数: count

SUM()

Page 53: 第四章  SQL 操纵功能

火眼金睛之一select S#

from SC

where GRADE = max( GRADE )

select S#

from SC

where GRADE =

(select max( GRADE )

from SC)

Page 54: 第四章  SQL 操纵功能

火眼金睛之一

count ( * ) VS count (列名)

S# C# G

s1 c1 80

s1 c2 90

s1 c3 95

s2 c1 85

s2 c2 null

s3 c2 null

4select count(G)

from SC

6

select count(*)

from SC

Page 55: 第四章  SQL 操纵功能

分组 分组命令

group by 列名 [having 条件表达式 ]

group by 将表中的元组按指定列上值相等的原则分组,然后在每一分组上使用聚集函数,得到单一值

having 则对分组进行选择,只将聚集函数作用到满足条件的分组上

Page 56: 第四章  SQL 操纵功能

分组和聚集函数 在关系的子集上运用聚集函数,得到一个新的

关系

Grouping Values

Partitioned Table

Sum()

Aggregate Values

Page 57: 第四章  SQL 操纵功能

分组

S# C# G

s1 c1 84

s1 c2 90

s1 c3 96

s2 c1 80

s2 c2 90

s3 c2 96

s3 c3 88

S# C# G

s1 c1 84

s1 c2 90

s1 c3 96

s2 c1 80

s2 c2 90

s3 c2 96

s3 c3 88

列出每个学生的平均成绩 列出每门课程的平均成绩

group by S# group by C#

92

85

90

92

92

90

Page 58: 第四章  SQL 操纵功能

火眼金睛之二R(A, B, C)

select A from R group by B

select A, B from R group by A

select A, C from R group by A, B

select A from R group by A, C

select A from R group by A

select * from R group by A, B

Page 59: 第四章  SQL 操纵功能

分组和聚集函数 示例

列出每个学生的最高、最低、平均成绩select S# , max(GRADE) ,

min(GRADE), avg(GRADE)

from SC

group by S#

Page 60: 第四章  SQL 操纵功能

分组和聚集函数 select S# , avg(GRADE) from SC group by S# having min(GRADE) >= 60

select S# , avg(GRADE) from SC

where GRADE >=60 group by S#

白马非马

Page 61: 第四章  SQL 操纵功能

分组和聚集函数 列出每一年龄组中男学生(超过 50人)的人数

select AGE , count(S#)

from S

where SEX = ‘M’

group by AGE

having count(*) > 50

Page 62: 第四章  SQL 操纵功能

分组和聚集函数 select avg(SAL) from DEPT group by D# having DNAME = ‘Computer Science’

select avg(SAL) from DEPT

where DNAME =‘Computer Science’

Page 63: 第四章  SQL 操纵功能

嵌套子查询 集合成员资格 集合之间的比较 集合基数的测试

测试集合是否为空 测试集合是否存在重复元组

Page 64: 第四章  SQL 操纵功能

集合成员资格: in 子查询

in 子查询表达式 [not] in (子查询)

判断表达式的值是否在子查询的结果中 示例

列出张军和王红同学的所有信息 select * from S where SNAME in

(‘ 张军’ , ’王红’ )

Page 65: 第四章  SQL 操纵功能

集合成员资格: in 子查询

选修了 c1 号课程的学生的姓名 select SNAME

from S, SC

where S.S# = SC.S#

and C# = c1)

select SNAME

from S

where S# in

(select S#

from SC

where C# = c1)

Page 66: 第四章  SQL 操纵功能

集合成员资格: in 子查询

列出选修了 c1 号和 c2 号课程的学生的学号 select S#

from SC

where SC.C# = c1

and S# in

(select S#

from SC

where C# = c2)

Page 67: 第四章  SQL 操纵功能

集合之间的比较: some/all 子查询

some/all 子查询 表达式 比较运算符 some (子查询) 表达式的值至少与子查询结果中的一个值相比满足

比较运算符 表达式 比较运算符 all (子查询) 表达式的值与子查询结果中的所有的值相比都满足

比较运算符

Page 68: 第四章  SQL 操纵功能

集合之间的比较: some/all 子查询

056

(5< some ) = true

05(5 some ) = true

05 ) = false(5< some

05 ) = true(5 = some

056

(5< all ) = false

46(5 all ) = true

610 ) = true(5< all

45 ) = false(5 = all

( all) not in(= all) in

(= some) in( some) not in

Page 69: 第四章  SQL 操纵功能

集合之间的比较: some/all 子查询

示例 找出平均成绩最高的学生号 select S#

from SC

group by S#

having avg(GRADE) >= all

(select avg(GRADE)

from SC

group by S#)

Page 70: 第四章  SQL 操纵功能

集合基数的测试: exists 子查询

测试集合是否为空[not] exists (子查询)

判断子查询的结果集合中是否有任何元组存在

in后的子查询与外层查询无关,每个子查询执行一次,而 exists 后的子查询与外层查询有关,需要执行多次,称之为相关子查询

Page 71: 第四章  SQL 操纵功能

集合基数的测试: exists 子查询

列出选修了 c1 号课程的学生姓名 select SNAME

from S

where exists

(select *

from SC

where C# = c1

and S# = S.S#)

S# SNAME

S1 A

S2 B

S3 C

S# C#

S1 c1

S2 c2

S3 c1

(s1,c1)

(s2,c1)

(s3,c1)

Page 72: 第四章  SQL 操纵功能

集合基数的测试: exists 子查询

列出选修了 c1 号和 c2 号课程的学生的学号 select S#

from SC SC1

where SC1.C# = c1

and exists

(select S#

from SC

where C# = c2

and S# = SC1.S#)

Page 73: 第四章  SQL 操纵功能

反半连接: not in, not exists

列出没有选修 c1 号课程的学生的姓名

# #

)()(S S

SCSS # #

)()(S S

SCS

select SNAME

from S

where S# not in

(select S#

from SC

where C# = c1)

select SNAME

from S

where not exists

(select S#

from SC

where S#=S.S#

and C# = c1)

Page 74: 第四章  SQL 操纵功能

反半连接: not in, not exists

select SNAME

from S

where S# in

((select S#

from S)

except

(select S#

from SC))

select SNAME

from (S left outer join SC

on S.S# = SC.S#)

where C# is null

Page 75: 第四章  SQL 操纵功能

除法在 SQL 中的表达

##,#)()(

CCSCSC existsnotexistsnot ...

Page 76: 第四章  SQL 操纵功能

列出选修了全部课程的学生姓名select SNAME

from S S1

where not exists

(select C#

from C C1

where not exists

(select *

from SC

where C# = C1.C#

and S# = S1.S# ))

任意课程,所求学生 s1 选之

不存在任何一门课程 c1 ,所求学生 s1没有选之

Page 77: 第四章  SQL 操纵功能

列出至少选修了 s1 号学生选修的所有课程的学生名select SNAMEfrom S S2where not exists

(select C#from C C1where exists

(select *from SC

where C# = C1.C# and S# = s1)

and not exists(select *from SC

where C# = C1.C#and S# = S2.S#)

任 意 课 程 , s1 号 学 生 选之,所求学生 s2 选之

不 存 在 任 何 一 门 课 程c1 , s1 号学生选之, s2没有选之

Page 78: 第四章  SQL 操纵功能

集合基数的测试 测试集合是否存在重复元组

unique ( 子查询)如果子查询结果中没有重复元组,则返回 true

Page 79: 第四章  SQL 操纵功能

集合基数的测试 示例

找出所有只教授一门课程的老师姓名 select PNAME

from PROF

where unique

(select P#

from PC

where PC.P# = PROF.P#)

Page 80: 第四章  SQL 操纵功能

集合基数的测试 找出至少选修了两门课程的学生姓名

select SNAME from S

where not unique(select S#from SC

where SC.S# = S.S#)

Page 81: 第四章  SQL 操纵功能

派生关系 命令

(子查询) as 关系名(列名,列名,…) SQL-92 中,允许在 from 子句中使用子查询表达

式,这时可将该子查询的结果命名为一个临时关系加以引用

派生关系 Vs 视图?

Page 82: 第四章  SQL 操纵功能

派生关系 示例

找出平均成绩及格的学生 先求每个学生的平均成绩,再从中找出及格的学生 select SNAME , avg(GRADE)

from S , SC

where SC.S# = S.S#

group by SNAME

Page 83: 第四章  SQL 操纵功能

派生关系select SNAME , AVG_GRADE

from

(select SNAME , avg ( GRADE)from S , SC

where SC.S# = S.S#

group by SNAME)

as result(SNAME , AVG_GRADE )

where AVG_GRADE >= 60

Page 84: 第四章  SQL 操纵功能

临时视图: DB2

with max-GRADE(value) as

select max (GRADE)

from SC

select S#

from SC, max-GRADE

where SC.GRADE = max-GRADE.value

Page 85: 第四章  SQL 操纵功能

临时视图: DB2

with S-total (S#, value) as

select S#, sum (GRADE)

from SC

group by S#

S-total-avg(value) as

select avg (value)

from S-total

select S#

from S-total, S-total-avg

where S-total.value >= S-total-avg.value

Page 86: 第四章  SQL 操纵功能

公用表表达式 CTE : SQL Server

with sum_T(s#, sum_G) as

(select s#, sum(grade)

from sc

group by s#)

Avg_Sum_T(avg_sum_G) as

(select avg(sum_G)

from sum_T)

select s#

from Sum_T, Avg_Sum_T

where sum_G > avg_sum_G

Page 87: 第四章  SQL 操纵功能

集合操作 命令

集合并: union (all)集合交: intersect (all)集合差: except (all)

集合操作缺省去除重复元组intersect 的优先级高于其他集合操作的优先级

Page 88: 第四章  SQL 操纵功能

集合操作S1={1, 1, 2, 2, 2}, S2={2, 2, 4}, S3={2, 4, 4}

S1 intersect S2 = {2},

S1 intersect all S2 = {2, 2};S1 except S2 = {1},

S1 except all S2 = {1, 1, 2},

S2 except S1 = S2 except all S1 = {4} 。S1 except all S2 intersect all S3 = {1, 1, 2, 2}

(S1 except all S2) intersect all S3 = {2}

Page 89: 第四章  SQL 操纵功能

集合操作 union 和 union all 在一起是不满足结合律的

select * from TableA

union all

(

select * from TableB

union

select * from TableC

)

(

select * from TableA

union all

select * from TableB

)

union

select * from TableC)

Page 90: 第四章  SQL 操纵功能

集合操作 示例

求工资大于 1000 或者年龄大于 60 的教工(select P#

from PROF

where SAL > 1000)

union

(select P#

from PROF

where AGE > 60)

(select P#

from PROF

where SAL > 1000

or AGE > 60

Page 91: 第四章  SQL 操纵功能

集合操作•R except S

select A

from (select 1 as flag, A

from R

union all

select 0, A

from S) RS

group by A

having count(distinct flag) = 1

and max(flag) = 1

(1 , a1)

(1 , a1)

(0 , a1)

Page 92: 第四章  SQL 操纵功能

集合操作•R except all S

select A

from (select A, max(Rcnt) – max(Scnt) as Cnt

from (select 1 as flag, A, count(*) Rcnt, 0

from R

group by A

union all

select 0, A, 0, count(*) Scnt

from S

group by A) RS_1

group by A) RS_2

join SeqNums on s_number <= Cnt

(a1, 2)

(1, a1, 3, 0)

(0, a1, 0, 1)

Page 93: 第四章  SQL 操纵功能

递归查询

trike

wheel frame

spoke tire seat pedal

rim tube

Assembly

part subpart

qty

trike wheel 3

trike frame 1

frame seat 1

frame pedal 1

wheel spoke 2

wheel tire 1

tire rim 1

tire tube 1

组成 trike 的零件有哪些?

Page 94: 第四章  SQL 操纵功能

递归查询R.part, S.subpart(Assemble)

R.part, S.subpart(R.subpart=S.part(R(Assemble) S(Assemble))

Assembly

part subpart

trike wheel

trike frame

frame seat

frame pedal

wheel spoke

wheel tire

tire rim

tire tube

Assembly

part subpart

trike seat

trike pedal

trike spoke

trike tire

wheel rim

wheel tube

R.part, T.subpart(R.subpart=S.part S.subpart=T.part(

R(Assemble) S(Assemble) T(Assemble))

Assembly

part subpart

trike rim

trike tube

Page 95: 第四章  SQL 操纵功能

递归查询: Oracle

Connect By

Select part, subpart

From Components

Start with part = ‘trike’

Connect by prior part = subpart

Page 96: 第四章  SQL 操纵功能

递归查询: DB2

with recursive Components(part, subpart) as

(select part, subpart

from Assembly)

union

(select A.part, C.subpart

from Assembly A, Components C

where A.subpart = C.part)

select * from Components

where part = ‘trike’

Page 97: 第四章  SQL 操纵功能

递归查询: SQL ServerWITH RecursiveCTE

AS

(

SELECT

FROM BaseTable

UNION ALL

SELECT

FROM RecursiveCTE

)

SELECT * FROM RecursiveCTE;

定位点成员Anchor Member

递归成员Recursive

Member

Page 98: 第四章  SQL 操纵功能

declare @root as INT;

set @root = 3;

with SubsCTE

as

(

select empid, ename, 0 as lvl

from emp

where e# = @root

union all

select C.#, C.ename, P.lvl + 1

from SubsCTE as P join emp AS C on C.mgrid = P.empid

)

select * from SubsCTE;

Page 99: 第四章  SQL 操纵功能

create function dbo.fn_subordinates(@root as int)

returns @Subs Table

(

empid int not null primary key ,

level int not null)

as

begin

declare @lvl as int;

set @lvl = 0; -- Initialize level counter with 0

insert into @Subs(empid, level) -- Insert root node to @Subs

select empid, @lvl

from emp

where empid = @root;

Page 100: 第四章  SQL 操纵功能

while @@rowcount > 0 -- while previous level had rows

begin

set @lvl = @lvl + 1; -- Increment level counter

-- Insert next level of subordinates to @Subs

insert into @Subs(empid, level)

select C.empid, @lvl

from @Subs AS P -- P = Parent

join emp AS C -- C = Child

on P.lvl = @lvl - 1 --Filter parents from previous level

and C.mgrid = P.empid;

end

return;

end

Page 101: 第四章  SQL 操纵功能

Prolog 程序 不是一系列动作,而是一组事实与规则的集合 是说明性语言,而非过程性语言 基于逻辑谓词 事实:对象间的一种关系,或对象的属性 规则:从一事实推出另一事实

自然语言A fast car is fun

Bill likes a car if the car is fun

逻辑谓词fun(fast-car)

likes(bill,car) if fun(car)

Page 102: 第四章  SQL 操纵功能

Prolog 程序规则

likes(cindy, Something) if

likes(bill, Something)

事实likes(bill, cindy)likes(cindy, bill)likes(bill, dog)

查询用户: likes(bill, cindy)系统: yes用户: likes(bill, What)系统: What = dog

What = cindy

查询用户: likes(cindy, What)系统: What = bill

What = dog What = cindy

Page 103: 第四章  SQL 操纵功能

Datalog 基本结构 Datalog由一组规则构成 Datalog 规则用来定义视图 Datalog 规则使用位置来识别关系的属性名

PROF(P#, PNAME, SAL, AGE, D#)给出退休了的老师的姓名和年龄

v1(A, B): – PROF(O, A, P, B, Q), B > 60

? v1(A, B) , B>80

v1 中所有年龄大于 80 的老师

? v1(“王明” , B)

v1 中王明老师的年龄

Page 104: 第四章  SQL 操纵功能

Datalog 基本结构 视图可以由多条规则来定义,视图中元组集合

为所有规则所定义的元组集合的并

tax-rate(A, 0): – PROF(A, B, C, D, E), C < 800tax-rate(A, 5): – PROF(A, B, C, D, E), C >= 800

工资超过 800 的老师缴纳 5% 所得税,低于 800 的免缴

v2(A): – S(A, B, C, D, E), not v3(A)v3(A): – SC(A, M, N)

给出所有没有选课的学生学号

Datalog 规则可以使用否定

Page 105: 第四章  SQL 操纵功能

Datalog 中的递归

Components(part, subpart) :- Assembly(part, subpart, Qty)

Components(part, subpart) :- Assembly(part, part2, Qty)

Components(part2, subpart)Big(part) :- Assembly(part, subpart, Qty), Qty > 2, not

Small(part)

Small(part) :- Assembly(part, part2, Qty), not Big(part)

不动点:f(v)=v

相互递归定义

Big trike

Small

frame

wheel

tire

Big

Small

trike

frame

wheel

tire

Page 106: 第四章  SQL 操纵功能

常用 SQL 函数:日期函数

getdate( ) :返回系统的当前日期 datepart( datepart, date ) :返回 date 中 的

datepart部分datepart( dd, '11/23/2008') = 23

datepart( yy, getdate( )) = 2009

day( date ) , month( date ) , year( date ):分别返回 date 中的“日”“月”“年”日期部分day('11/23/2009') = 23

month ('11/23/2009') = 11

year (getdate( )) = 2009

Page 107: 第四章  SQL 操纵功能

常用 SQL 函数:日期函数

datediff( datepart, startdate, endate ) :按照 datepart返回两个日期 startdate 和 endate

之差

datediff (mm, ‘8/1/2005’, getdate ())返回2005 年 8月 1 日和当前日期之间相隔的月数

dateadd(datepart, number, date) : 将number加到 date 的 datepart部分上

dateadd(dd, 20, '11/23/2009') =

'12/13/2009'

Page 108: 第四章  SQL 操纵功能

常用 SQL 函数:字符串函数

len( string_expression ) : 返 回string_expression 中的字符个数。如 len('China') = 5 。

lower( string_expression ) :返回小写 字 符 的string_expression 。 如 lower('China') = 'china' 。

upper( string_expression ) :返回大写 字 符 的string_expression 。 如 upper('China') = 'CHINA' 。

replicate ( string _expression ,integer_expression ) :按指定的次数 重 复 字 符 串 表 达 式 。 如 replicate ('ha', 3) = 'hahaha' 。

Page 109: 第四章  SQL 操纵功能

常用 SQL 函数:字符串函数

reverse( string_expression ) :返回字符表达式的 逆 向 表 达 式 。 如 reverse('databases') = 'sesabatad' 。

substring ( string_expression, start, length ) :从 string_expression 中由 start位置开始返回长度为 length 的部分字符串。如 substring (‘abcdef ’, 2, 3) = ‘bcd’ 。

replace (expression1, expression2, expression3 ) :用第三个表达式替换第一个表达式中 所 出 现 的 所 有 第 二 个 字 符 串 表 达 式 。 如replace('abcdefghicde', 'cde', 'xxx') = 'abxxxfghixxx' , replace('database', 'a', '') = 'dtbse' 。

Page 110: 第四章  SQL 操纵功能

常用 SQL 函数:字符串函数

计算指定字符在字符串中出现的次数selectlen('databases')

len(replace(‘databases’, ‘a’, ‘’))len('databases') 是整个字符串的长度,len(replace('databases', 'a', '') 是去掉 a 之后

的长度注意如果是检索多个字符的出现次数的话,还要除以相应的字符个数

selectlen('datadata') len(replace(‘datadata’, ‘ta’,

‘’))) / len(‘ta‘)

Page 111: 第四章  SQL 操纵功能

常用 SQL 函数:字符串函数

将字符串的每个字符单独作为一行输出

select substring(col_a, s_number, 1)

from

(select col_a, s_number

from (select 'datadata' col_a,

len('datadata') col_b) as Char_T1,

SeqNums

where col_b >= s_number) as Char_T2

Page 112: 第四章  SQL 操纵功能

SQL 的数据修改功能 插入 删除 修改

@@ROWCOUNT

返回受上一语句影响的行数 任何不返回行的语句将这一变量设置为 0

select * from S

select @@rowcount

Page 113: 第四章  SQL 操纵功能

插入操作 命令

insert into 表名 [ (列名 [ ,列名 ]…]values (值 [ ,值 ]…)

插入一条指定好值的元组

insert into 表名 [ (列名 [ ,列名 ]…](子查询)

插入子查询结果中的若干条元组

Page 114: 第四章  SQL 操纵功能

插入操作 示例

insert into PROF values ( P123, “王明” , 35, D08,

498 )

insert into PROF (P#, PNAME, D#)values ( P123, “王明” , D08 )

思考: SAL 取何值?

如何防止插入带有空值的元组?

Page 115: 第四章  SQL 操纵功能

插入操作 将平均成绩大于 90 的学生加入到 EXCELLENT 中

insert into EXCELLENT ( S#, GRADE)

select S# , avg(GRADE)

from SC

group by (S#)

having avg(GRADE) > 90

select S# , avg(GRADE)

into EXCELLENT ( S#, GRADE)

from SC

group by (S#)

having avg(GRADE) > 90

Page 116: 第四章  SQL 操纵功能

插入操作 复制一个数据文件至数据库表中

bulk insert 表名 from 数据文件with(batchsize = 指定批处理中的行数 ,check_constraints,datafiletype = 数据文件类型 ,fieldterminator = 字段终止符 , maxerrors = 所容忍的最大错误数目 , rowterminator = 行终止符 )

Page 117: 第四章  SQL 操纵功能

删除操作 命令

delete from 表名 [where 条件表达式 ]

从表 中 删 除 符 合 条 件 的 元 组 , 如果没有where 语句,则删除所有元组

示例 清除所有选课记录

delete from SC

Page 118: 第四章  SQL 操纵功能

删除操作 删除王明老师所有的任课记录

delete from PC

where P# in

(select P#

from PROF

where PNAME = “王明” )

Page 119: 第四章  SQL 操纵功能

删除操作 删除低于平均工资的老师记录

delete from PROF

where SAL <

(select avg(SAL)

from PROF)

思考:是先找到所有符合条件的元组,一并删除,还是找到一个删除一个?

Page 120: 第四章  SQL 操纵功能

删除操作 truncate table

删除表中的所有行,而不记录单个行删除操作 truncate table 在功能上与不带 where 子句的

delete 语句相同。但 truncate table 比 delete

速度快,且使用的系统和事务日志资源少 identity 计数器重置为种子值

Page 121: 第四章  SQL 操纵功能

更新操作 命令

update 表名 set 列名 = 表达式 | 子查询 列名 = [ ,表达式 | 子查询 ]…[where 条件表达式 ]

指定对哪些列进行更新,以及更新后的值是什么 示例

老师工资上调 5%update PROFset SAL = SAL * 1.05

Page 122: 第四章  SQL 操纵功能

更新操作 将 D01 系系主任的工资改为该系的平均工资

update PROF

set SAL =

(select avg(SAL)

from PROF

where D# = D01)

where P# =

(select DEAN

from DEPT

where D# = D01)

Page 123: 第四章  SQL 操纵功能

更新操作 当 C1 课程的成绩小于该课程的平均成绩时,将该

成绩提高 5%

update SC

set GRADE = GRADE * 1.05

where C# = C1

and GRADE <

(select avg(GRADE)

from SC

where C# = C1)

如果是对任何一门课程呢

Page 124: 第四章  SQL 操纵功能

更新操作 工资超过 2000 的缴纳 10% 所得税,其余的缴纳 5% 所得

税 ①

update PROF

set SAL = SAL * 0.9

where SAL > 2000

update PROF

set SAL = SAL * 0.95

where SAL <= 2000

update PROF

set SAL =

case SAL

when SAL > 2000 then SAL * 0.9

when SAL <= 2000 then SAL * 0.95

Page 125: 第四章  SQL 操纵功能

UPSERT 表同步

在把一组记录加载到表中时,一个经典的挑战是如何识别和处理目标表中已有的记录。常用的方法是如果某记录不存在,就将它插入;如果存在,就用源表中的数据 更新该记录

需要定义复杂的存储过程来完成一系列 INSERT 或UPDATE 命令,这个技术通常被称为 UPSERT(即Update…Insert)

Page 126: 第四章  SQL 操纵功能

表同步 跟踪购买习惯

数据仓库中的 FactBuyingHabits 表跟踪客户购买产品的最后日期,事务数据库每周都会生成一个包括该周采购情况的 PurchaseRecords 表

需要定期将 PurchaseRecords 表中的信息合并到FactBuyingHabits 表中。对于不存在的产品 -客户对,插入新行。对于已存在的产品 -客户对,更新最近的购买日期

Page 127: 第四章  SQL 操纵功能

表同步 跟踪价格历史记录

DimBook(ISBN 、 ProductID 、 Price 、 Shelf 和 IsCurrent)存储某书商库存中的图书列表,并标识每本书的价格历史记录。包含当前价格的那一行的 IsCurrent 被设置为 1

该数据库每周会生成一个 WeeklyChanges 表,包含该周的价格更改以及该周添加的新书。需要将WeeklyChanges 表的更改应用到 DimBook 表中。新添加的书插入新行,对于价格已更改的现有书的行,将这些行的 IsCurrent 更新为 0 ,为价格已更改的书插入新行,并将其 IsCurrent 设置为 1

Page 128: 第四章  SQL 操纵功能

MERGE MERGE 子句指定作为插入、更新或删除操作目标的

表或视图 USING 子句指定要与目标联接的数据源 ON 子句指定决定目标与源的匹配位置的联接条件 WHEN 子 句 ( WHEN MATCHED 、 WHEN NOT

MATCHED BY TARGET 和 WHEN NOT MATCHED BY SOURCE)基于 ON 子句的结果和在 WHEN 子句中指定的任何其他搜索条件指定所要采取的操作

OUTPUT 子句针对插入、更新或删除的目标中的每一行返回一行

Page 129: 第四章  SQL 操纵功能

MERGE

MERGE dbo.FactBuyingHabits AS Target

USING (SELECT CustomerID, ProductID, PurchaseDate

FROM dbo.Purchases) AS Source

ON (Target.ProductID = Source.ProductID

AND Target.CustomerID = Source.CustomerID)

WHEN MATCHED THEN

UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate

WHEN NOT MATCHED BY TARGET THEN

I INSERT (CustomerID, ProductID, LastPurchaseDate)

VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)

OUTPUT $action, Inserted.*, Deleted.*;