目录
1. 数据查询
① SELECT语句格式:
SELECT 【ALL | DISTINCT】<目标列表达式>【 , <目标列表达式>】...
FROM <表名或视图名>【 , <表名或视图名> 】... |(SELECT语句)【AS】<别名>
【WHERE <条件表达式>】
【GROUP BY <列名1> [HAVING <条件表达式>]】
【ORDER BY <列名2> [ASC | DESC] 】
② 目标列表达式格式
③ WHERE子句条件表达式格式
2. 单表查询
(1)选择表中的若干列
① 查询指定列
【例3.16】查询全体学生的学号与姓名
② 查询全部列
■ 选出所有属性列:
• 在SELECT关键字后面列出所有列名
• 将 <目标列表达式>指定为 *
【例3.18】查询全体学生的详细记录
③ 查询经过计算的值
■ “虚” 列
• SELECT 子句的 <目标表达式> 不仅可以为表中的属性列,也可以是表达式
算术表达式
字符串常量
函数
列别名
■ 算术表达式
【例3.19】查全体学生的姓名及其出生年份
■ 字符串常量及函数
【例3.20】查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名
■ 使用列别名改变查询结果的列标题:
(2)选择表中的若干元组
① 消除取值重复的行
■ 指定DISTINCT关键字,去掉表中重复的行
■ 如果没有指定DISTINGT关键字,则缺省为ALL
【例3.21】查询选修了课程的学生学号
② 查询满足条件的元组
❶ 比较大小
【例3.22】查询计算机科学系全体学生的名单
【例3.23】查询所欲年龄在20岁以下的学生姓名及其年龄
【例3,24】查考试成绩有不合格的学生的学号
❷ 确定范围
■ 谓词:BETWEEN...AND...
NOT BETWEEEN...AND...
【例3.25】查询年龄在20~23岁(包括20~23岁)之间的学生的姓名、系别和年龄
【例3.26】查询年龄b不在20~23岁之间的学生的姓名、系别和年龄
❸ 确定集合
■ 谓词:IN <值表>,NOT IN <值表>
【例3.27】查询计算机计科系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别
【例3.27】查询既不是计算机计科系、数学系,也不是信息系学生的姓名和性别
❹ 字符匹配
■ 谓词:【NOT】LIKE ' <匹配串> ' 【ESCCAPE ' <换码字符> '】
<匹配串>:可以是一个完整的字符串,也可以含有通配符%和 _
• %(百分号):代表任意长度(长度可以为0)的字符串
例如 a%b表示以a开头,以b结尾的任意长度的字符串
• _ (下横线):代表任意单个字符
例如a_b表示以a开头,以b结尾的长度为3的任意字符串
■ 匹配串为固定字符串
【例3.29】查询学号为201215121的学生号的详细情况
■ 匹配串为含通配符的字符串
【例3.30】查询所有姓刘的学生的姓名、学号和性别
【例3,31】查询姓 “欧阳” 且全名为三个汉字的学生的姓名
【例3.32】查询名字中第2个字为 “阳”字的学生的姓名和学号
【例3.33】查询所有不姓刘的学生姓名、学号和性别
■ 使用换码字符将通配符转义为普通字符
【例3.34】查询DB_Design课程的课程号和学分
【例3.35】查询以 “DB_”开头,且倒数第3个字符为 i 的课程的详细情况
❺ 涉及空值的查询
■ 谓词:IS NULL 或 IS NOT NULL
• “IS” 不能用 “=”代替
【例3.36】某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。
查询确实成绩的学生的学号和相应的课程号
❻ 多重条件查询
■ 逻辑运算符:AND 和 OR来连接多个查询条件
• AND的优先级高于OR
• 可以用括号改变优先级
【例3.38】查询计算机系年龄在20岁以下的学生姓名
■ 改写【例3.27】
【例3.27】查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别
(3)ORDER BY子句
■ ORDER BY子句
• 可以按一个或多个属性列排序
• 升序:ASC
降序:DESC
缺省值为升序
■ 对于空值,排序时显示的次序由具体系统实现来决定
【例3.39】查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列
【例3.40】查询全体学生情况,查询结果按所在系的系号升序排列, 同一系的学生按年龄降序排列
(4)聚集函数
■ 聚集函数
■ 聚集函数的一般格式
【例3.41】查询学生总人数
【例3.42】查询选修了课程的学生人数
【例3.43】计算1号课程的学生平均成绩
【例3.44】查询选修1号课程的学生最高分数
【例3.45】查询学生201215012选修课程的总学分数
(5)GUOUP BY子句
■ GUOUP BY子句分组:
细化聚集函数的作用对象
• 如果未对查询结果分组,聚集函数将作用于整个查询结果
• 对查询结果分组后,聚集函数将分别作用于每个组
• 按指定的一列或多列值分组,值相等的为一组
【例3.46】求各个课程号及相应的选课人数
【例3.47】查询选修了3门以上课程的学生学号
【例3.48】查询平局成绩大于等于90分学生学号和平均成绩
■ HAVING短语与WHERE子句的区别:
• 作用对象不同
• WHERE子句作用于基表或视图,从中选择满足条件的元组
• HAVING短语作用于组,从中选择满足条件的组
3. 连接查询
连接查询:不像关系代数中 “连接” 是用一个特殊符号来表达的,在SQL中“连接”是用“连接条件”来表达
连接条件或连接谓词:用来连接两个表的条件
一般格式:
【<表名1>.】<列名1><比较运算符>【<表名2>.】<列名2>
连接字段:连接谓词中的列名词
连接条件中的各连接字段类型必须是可比的,但名字不必相同
(1)等值与非等值连接查询
■ 等值连接:连接运算符 “=”
【例3.49】查询每个学生及其选修课程的情况
■ 自然连接
■ 采用在SELECT中去掉重复字段的方式实施
【例3.50】 对【例3,49】用自然连接完成
【例3.51】查询选修2课程且成绩在90以上所有学生的学号和姓名
(2)连接操作的执行过程
① 嵌套循环法(NESTED-LOOP)
■ 首先在表1中找到第一个元组,然后从头开始扫描表2,逐一查找满足连接件的元组,找到后就 将表1中的第一个元组与该元组拼接起来,形成结果表中一个元组
■ 表2全部查找完后,再找表1中第二个元组,然后再从头开始扫描表2,逐一找查满足连接条件的 元组,找到后就将表1中的第二个援助与该元组拼接起来,形成结果表中一个元组
■ 重复上述操作,直到表1中的全部元组都处理完毕
② 排序合并法(SORT-MERGE)
■ 常用于等值连接
■ 首先按连接属性对表1和表2排序
■ 设置指针,分别指向表1和表2的第一个元组。如果这两个元组满足连接条件,则进行元组拼接(如果有多个连续元组满足连接条件,则需要一一拼接),并将两指针分别后移一个原则。否 则,将具有较小值的指针后移一个元组
■ 重复上述操作,知道表1或表2中的全部元组都处理完毕为止
③ 索引连接(INDEX-JOIN)
■ 对表2按连接字段建立索引
■ 对表1中的每个元组,依次根据其连接字段值查询表2的索引,从中找到满足条件的元组,找到 后就将表1中的第一个元组与该元组拼接起来,形成结果表中的一个元组
■ (该方法可以视作嵌套环法的一个变种)
(3)自身连接
■ 自身连接:一个表与其自己进行连接,是一种特殊的连接
■ 需要给表起别名以示区别
■ 由于所有属性名都是同名属性,因此必须使用别名前缀
【例3.52】查询每一门的直接先修课的名称
(4)外连接
【例3.53】改写【例3.49】
(5)多表连接
■ 多表连接:两个以上的表进行连接
【例3.54】查询每个学生的学号、姓名、选修的课程名及成绩
4. 嵌套查询
(1) 嵌套查询概述
• 一个SELECT-FROM-WHERE语句称为一个查询块
• 将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询
■ 上层的查询块称为外层查询或父查询
■ 下层查询块称为内层查询或子查询
■ SQL语言允许多层嵌套查询
■ 子查询的限制
• 不能使用ORDER BY 子句
(2) 不相关的子查询
• 子查询的查询条件不依赖于父查询
• 由里向外 逐层处理,即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查 询的查找条件
(3) 相关子查询:子查询的查询条件依赖于父查询
• 首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若 WHERE子句返回值为真,则取此元组放入结果表
• 然后再去外层的下个元组
• 重复这一过程,直至外层表全部检查完为止
(4)带有IN谓词的子查询
【例3.55】查询与 “刘晨”在同一个系学习的学生
用自身连接完成【例3.55】查询要求
【例3.56】查询选修了课程名为 “信息系统”的学生学号和姓名
用连接查询实现【例3.56】
(5)带有比较运算符的子查询
■ 当确切知道内层查询返回值单值时,可用比较运算符(>,<,=,>=,<=,!=或<>)
【例3.55】中
【例3.57】找出每个学生超过他选修课程平均成绩的课程号
■ 可能的执行过程
• 从外层查询中取出SC的一个元组X,将元组X的Sno值(201215121)传递给内层查询
• 执行内层查询,得到88(近视值),用该值代替内层查询,得到外层查询:
• 然后外层查询取出下一个元组重复做上述1至3步骤,直到外层的SC元组全部处理完毕
(6)带有ANY(SOME)或ALL谓词的子查询
■ 在谓词逻辑中,还有存在量词和全称量词的概念
在SQL中并没有对应的表达,统一采用 “谓词”来表达
方法一:引入ANY和ALL谓词,其对象为某个查询结果,表示其中任意一个值或者全部值
方法二:引入EXIST谓词,其对象也是某个查询结果,但表示这个查询结果是否为空,返回真值
■ 使用ANY(SOME)或者ALL谓词的子查询
语义为:
【例3.58】查询非计算机科学系中比计算机科学系任意一个学生年龄小的学生姓名和年龄
■ 用聚集函数实现【例3.58】
【例3.59】查询非计算机科学系中比计算机科学系所有学生年龄都小的学生姓名及年龄
表3.7ANY(或SOME),ALL谓词与聚集函数、IN谓词的等价转换关系
(7)带有EXISTS谓词的子查询
■ EXISTS谓词
● 带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”
• 若内层查询结果为非空,则外层的WHERE子句返回真值
• 若内层查询结果为空,则外层的WHERE子句返回假值
● 由EXISTS引出的子查询,其目标列表达式通常都用 *,因为带EXISTS的子查询只返回真值或 假值,给出列名无实际意义
【例3.60】查询所有选修了1号课程的学生姓名
【例3.61】查询没有选修1号课程的学生姓名
■ 用EXISTS代替其他谓词
• 所有带IN谓词、比较运算符、ANY和ALL谓词的子查询都能带EXISTS谓词的子查询等价替换
■ 用EXISTS/NOT EXXISTS实现全称量词
■ 用EXISTS实现逻辑蕴含
• 可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:
【例3.55】查询与“刘晨”在同一个系学习的学生
可以用带EXISTS谓词的相关子查询替换:
【例3.62】查询选修了全部课程的学生姓名
■ 用EXISTS/NOT EXXISTS实现逻辑蕴含
• SQL语言中没有蕴含(Implication)逻辑运算
• 可以利用谓词演算将逻辑蕴含谓词等价转换为:
【例3.63】查询至少选修了学生201215122选修的全部课程的学生号码
5. 集合查询
(1)集合操作的种类
• 并操作(UNION)
· 将多个查询结果合并起来时,系统自动去掉重复元组
· UNION ALL:将多个查询结果合并起来时,保留重复元组
• 交操作(INTERSECT)
• 差操作(EXCEPPT)
■ 参加集合操作的各查询结果的列数必须相同;对应项的数据类型也必须相同
(2)集合操作举例
【例3.64】查询计算机科学系的学生及其年龄不大于19岁的学生
【例3.65】查询选修了课程1或者选修了课程2的学生
【例3.66】查询计算机科学系的学生与年龄不大于19岁的学生的交集
等价于
【例3.67】查询即选修了课程1又选修了课程2的学生
等价于
【例3.68】查询计算机科学系的学生与年龄不大于19岁的学生的差集
等价于