第四章 sql 操纵功能
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 PresentationTRANSCRIPT
SQL 数据操纵功能 SQL 数据查询功能
SQL 数据查询基本结构 select 子句 from 子句 where 子句 重复元组的处理 更名运算 元组显示顺序 字符串操作
SQL 数据查询功能 全文检索 关系的连接 分组和聚集函数 空值 派生关系 嵌套子查询 集合操作 递归查询
SQL 数据操纵功能 插入 删除 更新
SQL 数据查询基本结构 基本结构
select A1 , A2 , … , An
from r1 , r2 , … , rm
where P
∏A1 , A2 , … , An(p(r1 r2 … rm))
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
select 子句 目标列形式
可以为列名, * ,算术表达式,聚集函数 “*” :表示“所有的属性”
给出所有学生的所有信息select *from S
带,, , 的算术表达式给出所有学生的姓名及出生日期select SNAME , 2010- AGEfrom S
select 子句 将多个列组合为一列
示例:给出每个老师信息的自然语言描述。
select pname + ’ 老师的工资是’ + salary +
’, 年 龄 是 ’ + age + ’, 职 称是’ + titlefrom professor
输出行的形式类似:“ 李明老师的工资是 1500, 年龄是 45, 职称是教
授”
from 子句 from 子句列出查询的对象表 示例
找出选修课程的学生姓名、课程名、成绩
selectSNAME , CNAME, GRADEfrom S , C, SCwhere S.S# = SC.S#
and C.C# = SC.C#
GRADECNAMESNAMECSCS
,,)(
)C(C #.#.#.#. SCSSCS CCCSCSSCSS
乱花渐欲迷人眼
写出与 等价的 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
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 ?
重复元组的处理 语法约束
SQL 缺省为保留重复元组,也可用关键字 all 显式 指 明 。 若 要 去 掉 重 复 元 组 , 可 用 关 键 字distinct 指明
示例 找出所有选修课程的学生
select distinct S#
from SC
A(R) = (select A from R)?
重复元组的处理
查询一: 查询二: 查询三: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 可以去掉?
元组显示顺序 命令
order by 列名 [asc | desc] 示例
按年龄升序列出学生信息,相同年龄学生按姓名降序排列。
select *
from S
order by AGE asc , SNAME desc
元组显示顺序
示例:对教工按缴纳所得税的多少排序select fname, sal * 0.2
from faculty
order by 2
示例:按年龄顺序输出学生姓名select sname
from student
order by age
更名运算 格式
old_name as new_name
为关系和属性重新命名,可出现在 select和 from 子句中注: as 可选
更名运算 属性更名
例:给出所有学生的姓名、性别、出生日期,并按出生日期升序排列
select SNAME ‘ 姓名’ , SEX ‘ 性别’ ,
2007-AGE ‘ 出生日期’from S
order by 出生日期(或者 order by 3)
更名运算 关系更名
找出比 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
更名运算 找出工资比所在系主任工资高的老师姓名及工资
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
字符串操作 命令格式
列名 [not] like ‘ 字符串’找出满足给定匹配条件的字符串
匹配规则 ‘%’ :匹配零个或多个字符 ‘ _’:匹配任意单个字符 [ ] :任何在指定范围内的字符
[a-f] , [abcdef] [^] :任何不在指定范围内的字符
[^ a-f] , [^ abcdef]
字符串操作 Escape
定义转义字符,以去掉特殊字符的特定含义,使其被作为普通字符看待
如 escape ‘ \ ‘ ,定义 \ 作为转义字符,则可用 \% 去匹配 % ,用 \ _去匹配_
‘ %a_bx ’
select * from tt
where c1 like ‘x%%xx' escape ‘x'
思考:用什么去匹配 \ ?
字符串操作 示例
列出姓名以“张”打头的教师的所有信息 select *
from PROF
where PNAME like ‘ 张 % ‘ 列出名称中含有 3 个以上字符,且倒数第三个是
d ,倒数第二个是 _ 的课程select * from Cwhere CNAME LIKE ‘%_d\ _ _ ‘ escape ‘ \ ‘
字符串操作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
?
字符串操作在 CNAME 上建有索引 CNAME_idx ,观察下面查询的执行计划,看谁用到了该索引。
A. select * from C where CNAME like '%d'
B. select * from C where CNAME like 'd%'
小巫见大巫Like
全文索引 正则表达式
正则表达式 正则表达式( 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”
常见正则表达式 用户名:
/^[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+\/>)$/
正则表达式: Oracle
函数名 说明
REGEXP_LIKE类似于 LIKE 运算符,但执行正则表达式匹配而不是简单的模式匹配
REGEXP_INSTR在给定字符串中搜索某个正则表达式模式,并返回匹配项的位置
REGEXP_REPLACE
搜索某个正则表达式模式并使用替换字符串替换它
REGEXP_SUBSTR在给定字符串中搜索某个正则表达式模式并返回匹配的子字符串
正则表达式: 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')
全文检索
dialogue
Are you kidding?
No, I’m serious.
你是凯丁吗?不,我是史瑞斯。
create index idx1 on film(dialogus)
select * from film where dialogue like ‘%serious%’
全文检索
全文检索
正文
倒排索引
全文检索:创建
create fulltext catalog catalog_name
create fulltext index on table_name [(column_name ]
key index index_nameon catalog_name
key index 指定 table_name 上唯一键索引的名称,最好是聚簇索引
全文检索:查询
Contains( 属性列 |* ,查找条件 )
FREETEXT( 属性列 |* ,查找文本 ) 使用 FREETEXT 时,全文查询引擎内部将查找文
本拆分为若干个搜索词,并赋予每个词以不同的加权,然后查找匹配
全文检索 示例:全文索引的创建及使用演示
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
全文检索select*from documentswhere contains (*, 'database and
dataspace')
select*from documentswhere contains (author, 'Jim Gray and
not Jeff Ullman')
全文检索select*from documentswhere contains ((title, abstract), 'graph
mining')
select*from documentswhere freetext (content,
' Adaptive Query Processing')数据库查询和信息检索的区别
全文检索: SQL Server 2000
sp_fulltext_catalog 创建和除去全文目录,然后启动和停止目录的索引
操作。可为每个数据库创建多个全文目录
sp_fulltext_database 初始化全文索引,或者从当前数据库中删除所有的
全文目录
USE NorthwindEXEC sp_fulltext_database 'enable'
USE NorthwindEXEC sp_fulltext_catalog ’Northwind_FT’,’create’
全文检索: 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
全文检索: 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')
全文检索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*" ')
关系的连接 基本分类
连接成分包括两个输入关系、连接条件、连接类型
连接条件决定两个关系中哪些元组相互匹配,以及连接结果中出现哪些属性
连接类型决定如何处理与连接条件不匹配的元组
关系的连接
连接类型 连接条件
inner joinleft outer join
right outer joinfull outer join
on <谓词 >
(R cross join S) as T
两个关系的笛卡儿积
关系的连接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
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
关系的连接 列出老师的教工号、姓名、工资、所教课程号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)
空值
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
空值 空值测试
is [not] null测试指定列的值是否为空值
注意事项 除 is [not] null 之外,空值不满足任何查找条件 如果 null参与算术运算,则该算术表达式的值为
null 如果 null参与比较运算,则结果可视为 false 。在
SQL-92 中可看成 unknown表中存在两行 (1, 2, null), (1, 2, null) , select distinct * ?
空值 示例
找出成绩值为空的学生号 select S#
from SC
where GRADE is null
不可写为 where GRADE = null
空值 isnull
isnull(check_expression, replacement_value)
如 果 check_expression 值 为 空 , 则 返 回replacement_value, 否 则 返 回check_expression
select S#, C#, isnull ( GRADE, 0 )
from SC
空值 coalesce
coalesce(expression1, expression2, … ) ,返回第一个不为 null 的 expression
select s#, c#, coalesce(grade, 0)from sc
空值 缺省情况下空值是最后输出的。当指定 order by
时,降序情况下首先输出空值,升序情况下最后输出空值 示例:首先由小到大输出非空 sal ,然后是空值
salselect fname, sal
from faculty
order by 2 首先输出空值 sal ,然后由大到小输出非空 sal
select fname, sal
from faculty
order by 2 desc
空值 首先输出空值 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
聚集函数 聚集函数
将一列中所有的值聚集为单个值 平均值: avg 最小值: min 最大值: max 总和: sum 记数: count
SUM()
火眼金睛之一select S#
from SC
where GRADE = max( GRADE )
select S#
from SC
where GRADE =
(select max( GRADE )
from SC)
火眼金睛之一
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
分组 分组命令
group by 列名 [having 条件表达式 ]
group by 将表中的元组按指定列上值相等的原则分组,然后在每一分组上使用聚集函数,得到单一值
having 则对分组进行选择,只将聚集函数作用到满足条件的分组上
分组和聚集函数 在关系的子集上运用聚集函数,得到一个新的
关系
Grouping Values
Partitioned Table
Sum()
Aggregate Values
分组
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
火眼金睛之二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
分组和聚集函数 示例
列出每个学生的最高、最低、平均成绩select S# , max(GRADE) ,
min(GRADE), avg(GRADE)
from SC
group by S#
分组和聚集函数 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#
白马非马
分组和聚集函数 列出每一年龄组中男学生(超过 50人)的人数
select AGE , count(S#)
from S
where SEX = ‘M’
group by AGE
having count(*) > 50
分组和聚集函数 select avg(SAL) from DEPT group by D# having DNAME = ‘Computer Science’
select avg(SAL) from DEPT
where DNAME =‘Computer Science’
嵌套子查询 集合成员资格 集合之间的比较 集合基数的测试
测试集合是否为空 测试集合是否存在重复元组
集合成员资格: in 子查询
in 子查询表达式 [not] in (子查询)
判断表达式的值是否在子查询的结果中 示例
列出张军和王红同学的所有信息 select * from S where SNAME in
(‘ 张军’ , ’王红’ )
集合成员资格: 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)
集合成员资格: in 子查询
列出选修了 c1 号和 c2 号课程的学生的学号 select S#
from SC
where SC.C# = c1
and S# in
(select S#
from SC
where C# = c2)
集合之间的比较: some/all 子查询
some/all 子查询 表达式 比较运算符 some (子查询) 表达式的值至少与子查询结果中的一个值相比满足
比较运算符 表达式 比较运算符 all (子查询) 表达式的值与子查询结果中的所有的值相比都满足
比较运算符
集合之间的比较: 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
集合之间的比较: some/all 子查询
示例 找出平均成绩最高的学生号 select S#
from SC
group by S#
having avg(GRADE) >= all
(select avg(GRADE)
from SC
group by S#)
集合基数的测试: exists 子查询
测试集合是否为空[not] exists (子查询)
判断子查询的结果集合中是否有任何元组存在
in后的子查询与外层查询无关,每个子查询执行一次,而 exists 后的子查询与外层查询有关,需要执行多次,称之为相关子查询
集合基数的测试: 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)
集合基数的测试: 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#)
反半连接: 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)
反半连接: 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
除法在 SQL 中的表达
##,#)()(
CCSCSC existsnotexistsnot ...
列出选修了全部课程的学生姓名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没有选之
列出至少选修了 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没有选之
集合基数的测试 测试集合是否存在重复元组
unique ( 子查询)如果子查询结果中没有重复元组,则返回 true
集合基数的测试 示例
找出所有只教授一门课程的老师姓名 select PNAME
from PROF
where unique
(select P#
from PC
where PC.P# = PROF.P#)
集合基数的测试 找出至少选修了两门课程的学生姓名
select SNAME from S
where not unique(select S#from SC
where SC.S# = S.S#)
派生关系 命令
(子查询) as 关系名(列名,列名,…) SQL-92 中,允许在 from 子句中使用子查询表达
式,这时可将该子查询的结果命名为一个临时关系加以引用
派生关系 Vs 视图?
派生关系 示例
找出平均成绩及格的学生 先求每个学生的平均成绩,再从中找出及格的学生 select SNAME , avg(GRADE)
from S , SC
where SC.S# = S.S#
group by SNAME
派生关系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
临时视图: DB2
with max-GRADE(value) as
select max (GRADE)
from SC
select S#
from SC, max-GRADE
where SC.GRADE = max-GRADE.value
临时视图: 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
公用表表达式 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
集合操作 命令
集合并: union (all)集合交: intersect (all)集合差: except (all)
集合操作缺省去除重复元组intersect 的优先级高于其他集合操作的优先级
集合操作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}
集合操作 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)
集合操作 示例
求工资大于 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
集合操作•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)
集合操作•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)
递归查询
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 的零件有哪些?
递归查询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
递归查询: Oracle
Connect By
Select part, subpart
From Components
Start with part = ‘trike’
Connect by prior part = subpart
递归查询: 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’
递归查询: SQL ServerWITH RecursiveCTE
AS
(
SELECT
FROM BaseTable
UNION ALL
SELECT
FROM RecursiveCTE
)
SELECT * FROM RecursiveCTE;
定位点成员Anchor Member
递归成员Recursive
Member
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;
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;
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
Prolog 程序 不是一系列动作,而是一组事实与规则的集合 是说明性语言,而非过程性语言 基于逻辑谓词 事实:对象间的一种关系,或对象的属性 规则:从一事实推出另一事实
自然语言A fast car is fun
Bill likes a car if the car is fun
逻辑谓词fun(fast-car)
likes(bill,car) if fun(car)
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
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 中王明老师的年龄
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 规则可以使用否定
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
常用 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
常用 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'
常用 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' 。
常用 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' 。
常用 SQL 函数:字符串函数
计算指定字符在字符串中出现的次数selectlen('databases')
len(replace(‘databases’, ‘a’, ‘’))len('databases') 是整个字符串的长度,len(replace('databases', 'a', '') 是去掉 a 之后
的长度注意如果是检索多个字符的出现次数的话,还要除以相应的字符个数
selectlen('datadata') len(replace(‘datadata’, ‘ta’,
‘’))) / len(‘ta‘)
常用 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
SQL 的数据修改功能 插入 删除 修改
@@ROWCOUNT
返回受上一语句影响的行数 任何不返回行的语句将这一变量设置为 0
select * from S
select @@rowcount
插入操作 命令
insert into 表名 [ (列名 [ ,列名 ]…]values (值 [ ,值 ]…)
插入一条指定好值的元组
insert into 表名 [ (列名 [ ,列名 ]…](子查询)
插入子查询结果中的若干条元组
插入操作 示例
insert into PROF values ( P123, “王明” , 35, D08,
498 )
insert into PROF (P#, PNAME, D#)values ( P123, “王明” , D08 )
思考: SAL 取何值?
如何防止插入带有空值的元组?
插入操作 将平均成绩大于 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
插入操作 复制一个数据文件至数据库表中
bulk insert 表名 from 数据文件with(batchsize = 指定批处理中的行数 ,check_constraints,datafiletype = 数据文件类型 ,fieldterminator = 字段终止符 , maxerrors = 所容忍的最大错误数目 , rowterminator = 行终止符 )
删除操作 命令
delete from 表名 [where 条件表达式 ]
从表 中 删 除 符 合 条 件 的 元 组 , 如果没有where 语句,则删除所有元组
示例 清除所有选课记录
delete from SC
删除操作 删除王明老师所有的任课记录
delete from PC
where P# in
(select P#
from PROF
where PNAME = “王明” )
删除操作 删除低于平均工资的老师记录
delete from PROF
where SAL <
(select avg(SAL)
from PROF)
思考:是先找到所有符合条件的元组,一并删除,还是找到一个删除一个?
删除操作 truncate table
删除表中的所有行,而不记录单个行删除操作 truncate table 在功能上与不带 where 子句的
delete 语句相同。但 truncate table 比 delete
速度快,且使用的系统和事务日志资源少 identity 计数器重置为种子值
更新操作 命令
update 表名 set 列名 = 表达式 | 子查询 列名 = [ ,表达式 | 子查询 ]…[where 条件表达式 ]
指定对哪些列进行更新,以及更新后的值是什么 示例
老师工资上调 5%update PROFset SAL = SAL * 1.05
更新操作 将 D01 系系主任的工资改为该系的平均工资
update PROF
set SAL =
(select avg(SAL)
from PROF
where D# = D01)
where P# =
(select DEAN
from DEPT
where D# = D01)
更新操作 当 C1 课程的成绩小于该课程的平均成绩时,将该
成绩提高 5%
update SC
set GRADE = GRADE * 1.05
where C# = C1
and GRADE <
(select avg(GRADE)
from SC
where C# = C1)
如果是对任何一门课程呢
更新操作 工资超过 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
UPSERT 表同步
在把一组记录加载到表中时,一个经典的挑战是如何识别和处理目标表中已有的记录。常用的方法是如果某记录不存在,就将它插入;如果存在,就用源表中的数据 更新该记录
需要定义复杂的存储过程来完成一系列 INSERT 或UPDATE 命令,这个技术通常被称为 UPSERT(即Update…Insert)
表同步 跟踪购买习惯
数据仓库中的 FactBuyingHabits 表跟踪客户购买产品的最后日期,事务数据库每周都会生成一个包括该周采购情况的 PurchaseRecords 表
需要定期将 PurchaseRecords 表中的信息合并到FactBuyingHabits 表中。对于不存在的产品 -客户对,插入新行。对于已存在的产品 -客户对,更新最近的购买日期
表同步 跟踪价格历史记录
DimBook(ISBN 、 ProductID 、 Price 、 Shelf 和 IsCurrent)存储某书商库存中的图书列表,并标识每本书的价格历史记录。包含当前价格的那一行的 IsCurrent 被设置为 1
该数据库每周会生成一个 WeeklyChanges 表,包含该周的价格更改以及该周添加的新书。需要将WeeklyChanges 表的更改应用到 DimBook 表中。新添加的书插入新行,对于价格已更改的现有书的行,将这些行的 IsCurrent 更新为 0 ,为价格已更改的书插入新行,并将其 IsCurrent 设置为 1
MERGE MERGE 子句指定作为插入、更新或删除操作目标的
表或视图 USING 子句指定要与目标联接的数据源 ON 子句指定决定目标与源的匹配位置的联接条件 WHEN 子 句 ( WHEN MATCHED 、 WHEN NOT
MATCHED BY TARGET 和 WHEN NOT MATCHED BY SOURCE)基于 ON 子句的结果和在 WHEN 子句中指定的任何其他搜索条件指定所要采取的操作
OUTPUT 子句针对插入、更新或删除的目标中的每一行返回一行
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.*;