写在最前,
写文章的初衷只是为了复习与记录自己的成长,笔记本人也还是学生,文章中难免会出现许多问题与错误,文章内容仅供参考,有不足的地方还请大家多多包涵并指正,谢谢~
目录
第五章 查询处理和表数据编辑
SQL语言
SQL语言的全称为Structured Query Language(结构化查询语言),它利用一些语法简单命令实现数据库中的数据定义、数据操纵和数据控制功能。
结构化查询语言包括:数据查询语言、数据操作语言、事务处理语言、数据控制语言、数据定义语言、指针控制语言
5.1 查询数据
SELECT语句的格式:
SELECT [DISTINCT] <目标列表达式>[,…n]
FROM <表名或视图名> [,…n ]
[WHERE <条件表达式>]
[GROUP BY <列名1> [HAVING <条件表达式>] ]
[ORDER BY <列名2> [ASC | DESC] ]
SELECT语句的含义 :
根据WHERE条件,从FROM指定的表中找出满足条件的元组,按目标列表达式,选出属性值,形成结果表。
5.1.1 简单查询
最简单的查询
省略的一些可选成分,得最简单的查询命令:
SELECT [DISTINCT] <目标列表达式> [,…n ]
FROM <表名或视图名>
对一张表的某些列进行操作,功能为:
(1)查询指定列
(2)查询所有列
(3)查询计算列
(4)为列起别名
(5)使用DISTINCT关键字消除重复元组
查询指定列
--【例】查询全体学生的姓名、学号和电话号码
SELECT 姓名, 学号, 移动电话
FROM 学生表
各个列的输出顺序可以与表中的列顺序不同。用户查询时可根据需要改变列的显示顺序。
查询所有列
--【例】查询全体学生的详细信息
SELECT * --用“*”表示查询表的所有列。
FROM 学生表
查询计算列
查询也可以由常量、变量和函数构成的表达式
--【例】将累计学分降低10%后显示出来
SELECT 姓名,累计学分,累计学分-累计学分*0.1
FROM 学生表
计算列没有列名
查询结果为:
姓名 累计学分 (无列名)
王东民 2 1.8
张小芬 2 1.8
…
为列起别名
目的:满足用户的习惯,为计算列起名。方法:
① <目标列表达式> [AS] <别名>,AS可选
② <别名> = <目标列表达式>
--【例】将累计学分降低10%后显示,要求显示字母标题。
SELECT 姓名 AS name, 累计学分 Ogpa,
Ngpa=累计学分-累计学分*0.1
FROM 学生表
查询结果为:
name Ogpa Ngpa
王东民 2 1.8
…
注意:当别名含有空格时要用单引号括起
使用DISTINCT关键字消除重复元组
无DISTINCT时,结果中可能含重复行
有DISTINCT时,自动消除结果中的重复行
--【例】查询每个院系有在读学生的专业。
SELECT 所在院系, 专业
FROM 学生表
查询结果为:
所在院系 专业
信息学院 计算机
信息学院 计算机
……
结果中含重复行
SELECT DISTINCT 所在院系, 专业
FROM 学生表
查询结果为:
所在院系 专业
信息学院 计算机
信息学院 信息管理
……
结果中无重复行
DISTINCT应紧跟SELECT ,作为范围是整个查询列表,不是单独的某个列。
查询满足条件的元组
通过在WHERE子句中指定查询条件来实现
WHERE子句常用的查询条件:
查询条件 | 运算符(q) | 条件(逻辑表达式) | 备注 |
比较大小 | =, >, <, >=, <=, !=, <>, !>, !< | op1 q op2 | 双目运算 |
确定范围 | [NOT] BETWEEN AND | op1 [NOT] BETWEEN op2 AND op3 | 三目运算 |
确定集合 | [NOT] IN | op1 [NOT] IN op2 | 双目运算 |
字符匹配 | [NOT] LIKE | op1 [NOT] LIKE op2 | 双目运算 |
空值判断 | IS [NOT] NULL | op IS [NOT] NULL | 单目运算 |
组合条件 | NOT,AND,OR,( ) | NOT op, op1 AND op2, op1 OR op2 | NOT是单目, 其余是双目, 括号用于改变运算优先级 |
通过在WHERE子句中指定查询条件来实现
WHERE子句常用的查询条件:
(1) 比较大小
(2) 确定范围
(3) 确定集合
(4) 字符匹配
(5) 空值判断
(6) 组合条件
比较大小
查询条件: op1 θ op2
θ (比较运算符 ): =, >, <, >=, <=, !=, <>, !>, !<
op1 和 op2:由常量、变量、函数构成的算术/字符串表达式
--【例】查询来自杭州的所有学生。
SELECT * FROM 学生表
WHERE 籍贯='杭州'
--【例】查询累计学分在160分以下的学生姓名和累计学分。
SELECT 姓名, 累计学分 FROM 学生表
WHERE 累计学分<160
确定范围
查询条件: op1 [NOT] BETWEEN op2 AND op3
op1 、 op2、 op3:由常量、变量、函数构成的算术/字符串表达式。
--【例】查询累计学分不在150和159之间的学生姓名和累计学分。
SELECT 姓名, 累计学分 FROM 学生表
WHERE 累计学分 NOT BETWEEN 150 AND 159
--【例】查询姓名在’陈’和’李’之间的学生学号和姓名。
SELECT 学号, 姓名 FROM 学生表
WHERE 姓名 BETWEEN '陈' AND '李'
由字符串定义的范围是根据字符内码的顺序确定的(一般按字典顺序 )
确定集合
查询条件: op1 [NOT] IN op2
op1:由常量、变量、函数构成的算术/字符串表达式
op2:集合,表示为(e1, e2,…, en),其中e1, e2,…, en为集合的元素,它们可以是与op1同类型的常量、变量和函数构成的表达式。
含义:若op1(不)是集合op2的元素,则条件为真,否则为假。
--【例】查询来自杭州、宁波或温州的学生学号和姓名。
SELECT 学号,姓名 FROM 学生表
WHERE 籍贯 IN ('杭州','宁波','温州')
--【例】查询既不来自杭州,也不来自宁波的学号和姓名。
SELECT 学号,姓名 FROM 学生表
WHERE 籍贯 NOT IN ('杭州','宁波')
--【例】查询学号后两位是“09”,或者等于学号前两位或中间两位的学生学号和姓名。
SELECT 学号,姓名 FROM 学生表
WHERE SUBSTRING(学号,6,2) IN ('09',
SUBSTRING(学号,2,2),SUBSTRING (学号,4,2))
SUBSTRING(s,p,c):取子串函数,返回字符串s中从第p个字符开始,长度为c的子串。
字符匹配
查询条件: s1 [NOT] LIKE s2 [ESCAPE ’<换码字符>’]
s1和s2是由常量、变量、函数构成的字符串表达式。
s1称为主字符串,s2称为模式字符串 。
模式字符串除了包含普通字符外,还包含下列特殊字符(称为通配符):
% 匹配任意长度的字符串(长度可以为0)
_ 匹配任意一个字符
[c1c2…cn] 匹配字符c1, c2, …, cn中的一个。当c1, c2, …, cn连续时可简化为[c1-cn]
[^c1c2…cn] 匹配除c1, c2, …, cn外的一个字符。当c1, c2, …, cn连续时可简化为[^c1-cn]
含义:若s1(不)与s2相匹配,则条件为真,否则为假。
--【例】查询姓名中第二个字为“鹏”的学生学号和姓名。
SELECT 学号,姓名 FROM 学生表
WHERE 姓名 LIKE '_鹏%'
--【例】查询学号长度不等于7,或者学号后6位含有非数字字符的学生学号和姓名。
SELECT 学号,姓名 FROM 学生表
WHERE 学号 NOT LIKE
'S[0-9][0-9][0-9][0-9][0-9][0-9]'
--【例】查询学号最后一位既不是“1”和“3”,也不是“9”的学生学号和姓名。
SELECT 学号,姓名 FROM 学生表
WHERE 学号 LIKE '%[^139]'
ESCAPE短语: 使模式串中的某个通配符恢复原来的含义。
--【例】查询课程名以“DB_”开头的课程信息。
SELECT * FROM 课程表
WHERE 课名 LIKE 'DB\_%' ESCAPE '\'
空值判断
查询条件: exp IS [NOT] NULL
exp 是由常量、变量、函数构成的表达式。
含义:exp的值(不)为空值,则条件为真,否则为假。
--【例】查询没有成绩的学号和开课号。
SELECT 学号, 开课号 FROM 选课表
WHERE 成绩 IS NULL
注意“IS”不能用“=”代替。
--【例】查询有成绩的学号和开课号。
SELECT 学号, 开课号 FROM 选课表
WHERE 成绩 IS NOT NULL
注意“IS NOT”不能用“!=”或“<>”代替。
组合条件
查询条件: 用NOT、AND、OR和括号将多个逻辑表达式连接起来所得的复杂逻辑表达式 。
括号的优先级最高,NOT次之,AND再次之,OR的优先级最低。
--【例】查询这样的男生,他的电话号码前3位是“130”,他来自杭州或者宁波,他既不主修电子商务专业,也不主修信息管理专业。
SELECT * FROM 学生表
WHERE 性别='男' AND
SUBSTRING(移动电话,1,3)='130' AND
(籍贯='杭州' OR 籍贯='宁波') AND
NOT 专业 IN ('电子商务','信息管理')
对查询结果排序
用ORDER BY子句按照一个或多个列升序(ASC)或降序(DESC)输出查询结果,其中ASC为默认值
语法 :ORDER BY {<排序列> [ASC | DESC]}[,…n]
--【例】查询选修了开课号为’010101’的课程的学生学号和成绩,查询结果按分数降序排列
SELECT 学号, 成绩 FROM 选课表
WHERE 开课号 ='010101'
ORDER BY 成绩 DESC
可以用列在SELECT子句中的顺序编号来指定排序列,上例的ORDER BY子句可改为:ORDER BY 2 DESC
若需按SELECT子句中的计算列排序,则 ORDER BY子句可用三种方法来表示这个计算列:
1)列表达式;2)列顺序编号;3)列别名。
--【例】查询选修了开课号为’010101’的课程的学生学号、成绩以及加了10分后的新成绩,查询结果按原成绩降序、按新成绩升序排列。
SELECT 学号,成绩,成绩+10 AS New成绩
FROM 选课表 WHERE 开课号='010101'
ORDER BY 成绩 DESC, 成绩+10
上例中的成绩+10也可改写为:New成绩或3。
也可按SELECT子句中没有出现的列排序,此时不能用顺序编号来表示排序列。
5.1.2 统计
为了有效处理SQL查询结果集,SQL Server提供了一序列的统计函数,用来实现对数据集进行汇总、求平均等各种运算。
常用的统计函数
下表列出了常用的统计函数,其中DISTINCT表示统计时要剔除重复值。
函数格式 | 函数功能 |
COUNT([DISTINCT] *) | 统计元组个数 |
COUNT([DISTINCT] <列表达式>) | 统计列值的个数 |
SUM([DISTINCT] <列表达式>) | 计算数值型列表达式的总和 |
AVG([DISTINCT] <列表达式>) | 计算数值型列表达式的平均值 |
MAX([DISTINCT] <列表达式>) | 求列表达式的最大值 |
MIN([DISTINCT] <列表达式>) | 求列表达式的最小值 |
--【例】查询所有课本的总价格和平均价格,以及打七折后的总价格和平均价格。
SELECT SUM(定价), AVG(定价),
SUM(定价*0.7), AVG(定价*0.7)
FROM 课程表
查询结果为:
(无列名) (无列名) (无列名) (无列名)
93 31 65.1 21.7
关于本例有如下几条说明:
(1) 语句搜索了课程表的所有行,但只返回一行结果。
(2) 统计函数表示的列是计算列,结果无列名,可指定别名。
(3) 统计列值为空的元组不参与统计计算。
若结合WHERE子句来使用统计函数,则只有满足WHERE条件的行才参与统计。
--【例】查询课程编号前两位数字是’02’的课程所用课本的总价格和平均价格。
SELECT SUM(定价), AVG(定价) FROM 课程表
WHERE 课号 LIKE 'C02%'
在统计函数中可以用DISTINCT关键字来剔除重复值。
--【例】查询至少选修了一门课程的学生总数。
SELECT COUNT(DISTINCT 学号) FROM 选课表
COUNT(*)用来统计满足条件的元组个数。
--【例】查询课程编号前两位数字是’02’的课程总数。
SELECT COUNT(*) FROM 课程表
WHERE 课号 LIKE 'C02%'
分组查询
先对查询结果集进行分组,然后再对每个组进行统计,就要用到GROUP BY子句。
GROUP BY子句可以将查询结果集按一列或多列取值相等的原则进行分组。
含GROUP BY子句的查询称为分组查询。
使用GROUP BY子句进行分组
分组目的:细化统计函数的作用对象。
如果未对查询结果集分组,统计函数将作用于整个查询结果集,即整个查询结果集只有一个统计值。否则,统计函数将作用于每个组,即每一个组都有一个统计值。
GROUP BY子句的语法:GROUP BY <分组列>[,…n]
--【例】查询各门课程的课程号及相应的选课人数。
SELECT 开课号, COUNT(学号) FROM 选课表
GROUP BY 开课号
本例先对选课表按开课号的取值进行分组,所有具有相同开课号值的元组被分为一组,然后用COUNT函数统计每一组的学生人数。
注意:
① GROUP BY中的列名只能是FROM子句所列表的列名,不能是列的别名。例如下列查询是错误的:
SELECT 开课号 AS 开课计划编号, COUNT(学号)
FROM 选课表 GROUP BY 开课计划编号
② 使用GROUP BY子句后,SELECT子句的目标列表达式所涉及的列必须满足:要么在GROUP BY子句中,要么在在某个统计函数中。例如下列查询是错误的:
SELECT 开课号, 学号 FROM 选课表
GROUP BY 开课号
因为学号既不在GROUP BY子句中,也不在统计函数中。
使用HAVING短语来筛选组
HAVING短语的作用:指定组筛选条件。
--【例】查询学号前5位为’S0601’且选修了两门以上(含)课程的学生学号。
SELECT 学号 FROM 选课表
WHERE 学号 LIKE 'S0601%'
GROUP BY 学号 HAVING COUNT(*)>=2
WHERE子句与HAVING短语的区别
(1)作用对象不同:WHERE作用于表,HAVING作用于组。
(2)条件构成不同:WHERE条件不能直接包含统计函数,而 HAVING条件所涉及的列必须要么在GROUP BY子句中,要么在某个统计函数中。
5.1.3 连接查询
单表查询:仅涉及一个表的查询(FROM子句仅含一个表)。
连接查询:涉及多个表的查询(FROM子句包含多个表)。
连接查询和单表查询的区别和联系
区别:单表查询只涉及一张表,而连接查询涉及多张表。
联系:连接查询是针对多表笛卡尔积的单表查询。
连接查询的特殊性:
(1) 重名列加“<表名>.”前缀作为限定。
(2) WHERE条件:连接条件 [AND 普通查询条件]。
(3) 涉及n张表的连接查询至少应包括n-1个连接条件。
--【例】查询学生的基本信息及其选课信息。
SELECT 学生表.*, 开课号, 成绩
FROM 学生表, 选课表
WHERE 学生表.学号= 选课表 .学号
--【例】查询选修了开课号为“010101”的课程的学生学号和姓名。
SELECT 学生表.学号, 姓名 FROM 学生表, 选课表
WHERE 学生表.学号=选课表.学号 AND 开课号='010101'
为FROM子句后的表起别名
格式 :FROM {<表名> [ [AS] <别名> ] }[,…n]
目的:
(1)用别名作为列的前缀,缩短涉及重名列的子句。
(2)当FROM子句含多张相同的表时,必须为它们取不同的别名,在其他子句中用别名作为列的前缀。
--【例】查询至少选修了学号为“S060110”的学生所选一门课程的学生学号和姓名。
SELECT DISTINCT Z.学号, 姓名
FROM 选课表 AS X, 选课表 AS Y, 学生表 AS Z
WHERE X.学号='S060110' AND Y.学号!=X.学号 AND
Y.开课号 = X.开课号 AND Y.学号=Z.学号
使用JOIN…ON关键字
目的:将连接条件和普通查询条件分开。
格式:
SELECT子句
FROM <表名> {JOIN <表名> ON <连接条件> }[ …n ]
[WHERE <普通查询条件>]
[其他子句]
--【例】用JOIN和ON关键字实现上例的查询。
SELECT DISTINCT Z.学号, 姓名
FROM 选课表 X
JOIN 选课表 Y ON Y.学号!=X.学号 AND Y.开课号 = X.开课号
JOIN 学生表 Z ON Y.学号=Z.学号
WHERE X.学号='S060110'
外连接
种类:左外连接、右外连接、全外连接
左外连接:将左边关系中的未用元组配上空值加到结果集中。操作符: *= 或 LEFT OUTER JOIN…ON。
右外连接:将右边关系中的未用元组配上空值加到结果集中。操作符: =*或 RIGHT OUTER JOIN…ON。
全外连接:将两边关系中的未用元组配上空值加到结果集中。操作符: FULL OUTER JOIN…ON。
--【例】查询学生的学号、姓名、籍贯信息及其选课信息,分别以左外连接、右外连接和全外连接显示。
--(1)左外连接
SELECT 学生表.学号, 姓名, 籍贯, 开课号, 成绩
FROM 学生表 LEFT OUTER JOIN 选课表ON 学生表.学号=选课表.学号
查询结果为:
学号 姓名 籍贯 开课号 成绩
S060101 王东民 杭州 010101 90
……………………………………………
S060109 陈晓莉 西安 NULL NULL
……………………………………………
--【例】查询学生的学号、姓名、籍贯信息及其选课信息,分别以左外连接、右外连接和全外连接显示。
--(2)右外连接
SELECT 学生表.学号, 姓名, 籍贯, 开课号, 成绩
FROM 学生表 RIGHT OUTER JOIN 选课表 ON 学生表.学号= 选课表.学号
--(3)全外连接
SELECT 学生表.学号, 姓名, 籍贯, 开课号, 成绩
FROM 学生表 FULL OUTER JOIN 选课表 ON 学生表.学号= 选课表.学号
5.1.4 子查询
查询块: ( SELECT语句 ),代表查询的中间结果集。
子查询:将一个查询块嵌入另一个中,称嵌套查询。上层查询块称父查询,下层查询块称子查询。
用途:对子查询进行集合检查来表达查询条件。
子查询检查方法:
1.检查给定值是否在结果集中
2.用给定值和结果集中的元素进行大小比较
3.检查结果集是否为空
检查给定值是否在结果集中
查询条件:父查询的属性列 IN (子查询)。
含义:判断属性列的值是否在子查询的结果中。
--【例】查询选修了 “数据库原理”的学生学号和姓名。
SELECT 学号, 姓名 FROM 学生表
WHERE 学号 IN ( SELECT 学号 FROM 选课表
WHERE 开课号 IN ( SELECT 开课号 FROM 开课表
WHERE 课号 IN ( SELECT 课号 FROM 课程表
WHERE 课名=‘数据库原理’ ) ) )
嵌套查询的特点:
(1)允许多层嵌套,求解顺序:由内向外。
(2)对用IN或比较运算符连接的子查询,其SELECT子句只能有一个列表达式,且左边列表达式和右边SELECT中的列表达式含义要相同。
用给定值和结果集中的元素进行大小比较
含义:指父查询与子查询之间用比较运算符进行连接。分为单值比较和多值比较两类。
(1)单值比较
当子查询的结果集只包含一个值时,可用比较运算符直接连接父查询的列表达式和子查询结果集,实现其间的大小比较。
返回单值的子查询可参加任何合法的表达式运算。
--【例】查询累计学分比“胡汉民”多2分以上(含)的学生学号、姓名和累计学分。
SELECT 学号, 姓名, 累计学分 FROM 学生表
WHERE 累计学分 >= ( SELECT 累计学分 FROM 学生表
WHERE 姓名 = '胡汉民' ) + 2
--【例】查询学生S060101的姓名和平均成绩
SELECT 姓名, ( SELECT AVG(成绩) FROM 选课表
WHERE 学号='S060101' )
FROM 学生表 WHERE 学号='S060101'
(2)多值比较
当子查询的结果集包含多个值时,用给定值和结果集中的某个值进行的比较。此时父查询与子查询之间要用比较运算符后缀ANY或ALL进行连接,其含义见下表。
比较运算 | 含义 |
>ANY、 >=ANY | 大于、大于等于子查询结果集中的某个值 |
<ANY、<=ANY | 小于、小于等于子查询结果集中的某个值 |
= ANY | 等于子查询结果集中的某个值 |
!=ANY或<>ANY | 不等于子查询结果集中的某个值 (无意义) |
>ALL、 >=ALL | 大于、大于等于子查询结果集中的所有值 |
<ALL、<=ALL | 小于、小于等于子查询结果集中的所有值 |
=ALL | 等于子查询结果集中的所有值(无意义) |
!=ALL或<>ALL | 不等于子查询结果集中的所有值 |
--【例】查询累计学分比计算机专业和信息管理专业所有学生都低的学生名单。
SELECT 姓名 FROM 学生表
WHERE 专业 <>'计算机' AND 专业 <>'信息管理' AND
累计学分 <ALL ( SELECT 累计学分 FROM 学生表
WHERE 专业 IN (‘计算机' , '信息管理') )
本例也可以用统计函数实现:
SELECT 姓名 FROM 学生表
WHERE 专业 <>'计算机' AND 专业 <>'信息管理' AND
累计学分 < ( SELECT MIN(累计学分) FROM 学生表
WHERE 专业 IN (‘计算机’ , ‘信息管理’))
检查结果集是否为空
语法:[NOT] EXISTS (子查询)
EXISTS:子查询结果集不空则返回真,否则返回假
NOT EXISTS:子查询结果集为空则返回真,否则返回假
--【例】查询选修了开课计划号为010101的学生姓名。
SELECT 姓名 FROM 学生表 AS S
WHERE EXISTS ( SELECT * FROM 选课表 AS E
WHERE E.学号=S.学号 AND 开课号='010101' )
这类子查询具有如下特点:
(1)子查询的条件往往要引用上层查询所涉及的表。
(2)子查询的SELECT子句写成SELECT *即可。
5.1.5 联合查询
目的:把多个SELECT语句的结果合并为一个
格式: SELECT语句 [UNION SELECT语句][ …n]
特点:
(1)各结果表的列数、对应列的数据类型必须相同。
(2)结果表的列名取第1个SELECT语句定义的列名。
(3)系统会自动去掉重复的元组。
--【例】查询计算机专业和信息管理专业的学生信息。
SELECT * FROM 学生表 WHERE 专业='计算机'
UNION
SELECT * FROM 学生表 WHERE 专业='信息管理'
5.2 表数据编辑
表数据编辑又称数据更新,包括插入数据、修改数据和删除数据三类命令。
插入数据
1.插入单个元组:
INSERT…VALUES语句, 格式为:
INSERT [INTO] <表名> [ ( <列名>[,…n] ) ]
VALUES ( <表达式>[,…n] )
注意:
(1)未出现在列名列表中的列插入时取空值;
(2)表达式数量必须和列名数量相等,表达式的数据类型必须和对应列的数据类型相兼容;
(3)关系中的NOT NULL列必须出现在列名列表中;
(4)若省略列名列表,则VALUES须指定所有列的值。
--【例】将(’S060102’, ’010201’)插入选课表表。
INSERT INTO 选课表 (学号, 开课号)
VALUES ('S060102', '010201')
2.插入子查询的结果:
INSERT…SELECT语句, 格式为:
INSERT [INTO] <表名> [ ( <列名>[,…n] ) ]
SELECT语句
注意:
(1)未出现在列名列表中的列插入时取空值;
(2)SELECT中的目标列须和INSERT中的列数量相等、类型兼容;
(3)关系中的NOT NULL列须出现在列名表和SELECT语句中;
(4)若省略列名列表,则SELECT语句须指定所有列的值。
--【例】求各个专业学生的平均累计学分,把结果存入表中。
CREATE TABLE 主修专业 ( 专业 CHAR(20), Avgpa INT)
INSERT INTO 主修专业(专业, Avgpa)
SELECT 专业, AVG(累计学分) FROM 学生表
GROUP BY 专业
3.使用SELECT…INTO语句进行数据插入
格式为:
SELECT <目标列>[,…n] INTO <新表名>
[ SELECT语句的其他子句 ]
注意:
(1)系统会自动创建一个新表,新表的结构由目标列表达式定义,然后将 SELECT 语句的结果集插入这个新表 ;
(2)当目标列是计算列时,必须为它起别名。
--【例】用SELECT … INTO语句改写上例。
SELECT 专业, AVG(累计学分) AS Avgpa INTO 主修专业
FROM 学生表
GROUP BY 专业
修改数据
1.数据修改语句:
UPDATE, 格式为:
UPDATE <表名> SET {<列名> = <表达式>}[,…n]
[ FROM <表名>[,…n] ]
[ WHERE <修改条件> ]
注意:
(1)UPDATE语句用来修改指定表中满足WHERE条件的元组。修改方法是用SET子句中<表达式>的值取代相应列的值 ;
(2)修改条件和SELECT语句中WHERE条件完全相同,它不仅可以直接使用UPDATE后面的表,也可通过引入FROM子句直接使用其他表,还可以将子查询嵌入修改条件中。
2.修改给定表的所有行
若省略WHERE子句,则UPDATE将修改表的所有行。
--【例】将所有学生的累计学分增加3分。
UPDATE 学生表 SET 累计学分=累计学分+3
3.基于给定表修改某些行
如果省略FROM子句,但含有WHERE子句,则UPDATE语句将修改满足修改条件的行,但是此时的修改条件只能直接使用UPDATE后面的表所包含的列。
--【例】将计算机专业所有女生的籍贯改为“杭州”,累计学分增加3分。
UPDATE 学生表 SET 累计学分=累计学分+3, 籍贯='杭州'
WHERE 专业 = '计算机' AND 性别 = '女'
4.基于其他表修改某些行
如果修改条件需要使用其他表的列,就要用FROM子句将这些表引入到UPDATE语句中。
--【例】将计算机专业所有学生的数据库原理课程的成绩增加10分。
UPDATE 选课表 SET 成绩 = 成绩+10
FROM 开课表 AS O, 课程表 AS C, 学生表 AS S
WHERE 专业='计算机' AND
课名='数据库原理' AND
C.课号 = O.课号 AND
O.开课号 = 选课表.开课号 AND
选课表.学号 = S.学号
5.用子查询修改某些行
UPDATE中的修改条件还可以通过嵌入子查询进行构造。
--【例】用子查询构造上例的修改条件,实现相同功能。
UPDATE 选课表 SET 成绩 = 成绩+10
FROM 学生表 AS S
WHERE 专业='计算机' AND 选课表.学号=S.学号 AND 开课号 IN (
SELECT 开课号 FROM 开课表
WHERE 课号 IN (
SELECT 课号 FROM 课程表
WHERE 课名='数据库原理' ) )
删除数据
1.数据删除语句:
DELETE, 格式为:
DELETE [FROM] <目标表名>
[ FROM <表名>[,…n] ]
[ WHERE <删除条件> ]
注意:
(1) DELETE语句用来删除指定表中满足删除条件的元组;
(2)删除条件和SELECT语句中WHERE条件完全相同,它不仅可以直接使用DELETE后面的表,也可通过引入FROM子句直接使用其他表,还可以将子查询嵌入删除条件中。
2.删除给定表的所有行
若省略WHERE子句,则DELETE将删除表的所有行。
--【例】将学生表表清空。
DELETE FROM 学生表
3.基于给定表删除某些行
如果省略FROM子句,但含有WHERE子句,则DELETE语句将删除满足删除条件的行,但是此时的删除条件只能直接使用DELETE后面的表所包含的列。
--【例】从学生表表中删除计算机专业所有女生的信息。
DELETE FROM 学生表
WHERE 专业 = '计算机' AND 性别 = '女'
4.基于其他表删除某些行
如果删除条件需要使用其他表的列,就要用FROM子句将这些表引入到DELETE语句中。
--【例】从选课表表中删除计算机专业所有学生对数据库原理课程的选修信息。
DELETE FROM 选课表
FROM 开课表 AS O, 课程表 AS C, 学生表 AS S
WHERE 专业='计算机' AND
课名='数据库原理' AND
C.课号 = O.课号 AND
O.开课号 = 选课表.开课号 AND
选课表.学号 = S.学号
5.用子查询删除某些行
DELETE中的删除条件还可以通过嵌入子查询进行构造。
--【例】用子查询构造上例的删除条件,实现相同功能。
DELETE FROM 选课表
FROM 学生表 AS S
WHERE 专业='计算机' AND 选课表.学号=S.学号 AND 开课号 IN (
SELECT 开课号 FROM 开课表
WHERE 课号 IN (
SELECT 课号 FROM 课程表
WHERE 课名='数据库原理' ) )
5.3 大文本和图像数据处理
处理大文本和图像数据的数据类型:
TEXT: 长达2GB的ASCII字符串
NTEXT:长达1GB的UNICODE字符串
IMAGE:长达2GB的二进制数据流
大文本和图像数据列的定义和使用
若列值的长度不超过8000字节,就可在SELECT、UPDATE和INSERT语句中引用它们。
--【例☆】首先创建表,其中含一个TEXT列,然后插入一些元组,最后用显示内容。
CREATE TABLE Textdemo( Item INT PRIMARY KEY,Textstring TEXT )
INSERT INTO Textdemo VALUES(1, NULL)
INSERT INTO Textdemo
VALUES(2, 'Education is more all-inclusive than schooling')
INSERT INTO Textdemo
VALUES(3, REPLICATE('Education is all-inclusive', 4) )
SELECT * FROM Textdemo
若长度超过8000字节,处理时会发生数据截尾。
用于大文本和图像数据处理的函数和语句
1.获取大文本和图像列的指针和数据长度
TEXTPTR(列名):获取大文本和图像列的数据指针
DATALENGTH(列名): 获取数据长度
--【例】显示例☆中Textstring列的数据指针和长度。
SELECT Item, TEXTPTR(Textstring) AS指针,
DATALENGTH(Textstring) AS长度
FROM Textdemo
执行结果为:
Item 指针 长度 x
1 NULL NULL
2 0xFFFFA001000000008300000001000000 46
3 0xFFFFA101000000008300000001000200 104
2.检测大文本和图像列指针的有效性
格式:TEXTVALID('<表名>.<列名>', <数据指针>) 。
返回值:如果数据指针有效,则返回1,否则返回0。
--【例】显示例☆中数据指针有效的列值及其长度。
SELECT DATALENGTH(Textstring) AS 长度, Textstring
FROM Textdemo
WHERE TEXTVALID ( 'Textdemo.Textstring',
TEXTPTR(Textstring) ) = 1
执行结果为:
长度 Textstring x
46 Education is more all-inclusive than schooling
104 Education is all-inclusiveEducation is...
3.通过指针读大文本和图像列
格式:READTEXT <表名>.<列名> <数据指针> offset size [HOLDLOCK]
含义: 在<数据指针>所指数据中返回从offset开始的size个字符。如果使用了HOLDLOCK关键字,则读取时对数据进行加锁。注意offset是从0开始的。
--【例】显示例☆中Item为2的元组的列值前20个字符。
DECLARE @ptr VARCHAR(16)
SELECT @ptr=TEXTPTR(Textstring) FROM Textdemo
WHERE Item=2
READTEXT Textdemo.Textstring @ptr 0 20 HOLDLOCK
执行结果为:
Textstring x
Education is more al
DECLARE @变量名 变量类型 定义变量
4.通过指针写大文本和图像列,
格式:WRITETEXT <表名>.<列名> <数据指针> [WITH LOG] data
含义: 将数据data写入<数据指针>所指的列,覆盖原有数据。如果使用了WITH LOG关键字,则要记录日志。
--【例】向例☆中Item为1的元组的列写入数据。
UPDATE Textdemo SET Textstring='TRY' WHERE Item=1
DECLARE @ptr VARCHAR(16)
SELECT @ptr=TEXTPTR(Textstring)
FROM Textdemo WHERE Item=1
WRITETEXT Textdemo.Textstring @ptr ‘I think so.’
SELECT * FROM Textdemo WHERE Item=1
执行结果为:
Item Textstring x
1 I think so.
5.通过指针修改大文本和图像列
格式:UPDATETEXT <目标表名>.<目标列名> <目标数据指针> <位置>
<长度> [ WITH LOG ] [ <要插入的数据> | <源表名>.<源列名>
<源数据指针> ]
功能:
(1)若不给出<要插入的数据>和<源表名>.<源列名> <源数据指针>,则从<位置>处开始删除<目标表名>.<目标列名> <目标数据指针>所指数据的<长度>个字符。
(2)若给出了<要插入的数据>或<源表名>.<源列名> <源数据指针>,则将数据源插入到<目标数据指针>所指数据的第<位置>个字符位置处。插入的数据可直接给出,也可通过<源表名>.<源列名> <源数据指针>给出。此时<位置>和<长度>各种组合的含义见下表。
表 UPDATETEXT语句中<位置>和<长度>各种组合的含义 | ||
位置 | 长度 | 含义 |
NULL | NULL | 将源数据追加到目标数据值的尾部 |
非NULL | NULL | 用源数据替换目标数据中从<位置>开始到末尾的所有数据 |
非NULL | 0 | 将源数据插入到目标数据的<位置>处 |
非NULL | 非NULL且非0 | 用源数据替换目标数据中从<位置>开始的<长度>个字符 |
--【例】在Textdemo表中删除Item为2的元组的Textstring列的数据片断,这个片断从位置2开始,长度为10个字符。
DECLARE @ptr VARCHAR(16)
SELECT @ptr=TEXTPTR(Textstring) FROM Textdemo
WHERE Item=2
UPDATETEXT Textdemo.Textstring @ptr 2 10
SELECT * FROM Textdemo WHERE Item=2
执行结果为:
Item Textstring x
2 Ed more all-inclusive than schooling
--【例】在Textdemo表中,将Item为2的元组的Textstring列插入Item为3的元组的Textstring列首部。
DECLARE @ptrs VARCHAR(16), @ptrd VARCHAR(16)
SELECT @ptrs=TEXTPTR(Textstring) FROM Textdemo
WHERE Item=2
SELECT @ptrs=TEXTPTR(Textstring) FROM Textdemo
WHERE Item=3
UPDATETEXT Textdemo.Textstring @ptrd 0 0
Textdemo.Textstring @ptrs
SELECT * FROM Textdemo WHERE Item=2 OR Item=3
执行结果为:
Item Textstring x
2 Ed more all-inclusive than schooling
3 Ed more all-inclusive than schoolingEducation is…
写在最后,
因本系列文章主要为复习,故重点关注数据库概念知识与理论知识,涉及使用对象资源管理器操作数据库的内容就不再赘述,笔记仅作为参考,若读者发现内容有误请私信指正,谢谢!