嵌套查询实验
嵌套查询实验
1. 基础知识
一个SELECT-FROM-WHERE语句称为一个查询块。
将一个查询块嵌套在另一个查询块的WHERE子句或HAVING短语的条件中的查询称为嵌套查询。
可以参看例1。
>> 根据求解过程分子查询主要有
(1)不相关子查询
子查询的查询条件不依赖于父查询;
由里向外,逐层处理。即每个子查询在上一级查询处理之前求解,子查询的结果用于建立其父查询的查找条件。
(2)相关子查询
子查询的查询条件依赖于父查询。
首先取外层查询中表的第一个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句返回值为真,则取此元组放入结果表;
然后再取外层表的下一个元组;
重复这一过程,直至外层表全部检查完为止。
>>根据嵌套的子句类型分嵌套查询主要类型
1)带有IN谓词的子查询
2)带有比较运算符的子查询
3)带有ANY(SOME)或ALL谓词的子查询
4)带有EXISTS谓词的子查询
2. 实验案例
1)带有IN谓词的子查询。
例1.查询选修了2号课程的学生姓名。
[sql] view plaincopyprint?
--外查询:查询学号在子查询结果内的学生姓名。
select sname
from student
where sno in (
--子查询:查询选修了2号课程的学生学号。
select sno
from sc
where cno = '2'
)
>>说明:
(1)以上查询中子查询跟外查询没关系,所以可以先做子查询,把结果作为外查询的where子句的一部分,再进行外查询的筛选条件得到结果,这种与外查询没关系的子查询称为为“不相关子查询”。
(2)子查询的限制“不能使用ORDER BY子句”。为什么?子查询是个中间结果,而排序只能对查询结果进行。
(3)层层嵌套方式反映了 SQL语言的结构化。
(4)有些嵌套查询可以用连接运算替代。把例1改成连接运算?
select sname
from student,sc
where student.sno = sc.sno and sc.cno = '2'
2)带有比较运算符的子查询
例2.查询每个学生学号和超过他选修课程平均成绩的课程号。
SELECT Sno,Cno
FROM SC x
WHERE Grade >=
(SELECT AVG(Grade)
FROM SC y
WHEREy.Sno=x.Sno);
>>执行过程
<1> 从外层查询中取出SC的游标指向的(首次为第一行)元组x,将元组x的Sno值(200215121)传送给内层查询。
SELECTAVG(Grade)
FROM SC y
WHERE y.Sno='200215121';
<2> 执行内层查询,得到值88(近似值),用该值代替内层查询,得到外层查询的查询条件,判断外层查询的当前元组是否满足条件:(满足,则该元组进入结果集,不满足时则不进入结果集)。
SELECTSno, Cno
FROM SC x
WHERE Grade >=88;
<3>外查询表游标下移,如果到了表的尾部,进入下一步结束。否则,返回第一步。
<4>结束。
>>说明:
当能确切知道内层查询返回单值时,可用比较运算符(>,<,=,>=,<=,!=或< >)。
与ANY或ALL谓词配合使用
3)带有ANY(SOME)或ALL谓词的子查询
例3.查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄
SELECT _______ , _______
FROM ___________
WHERE Sage < ________(SELECT _________
FROM Student
WHERE Sdept= 'CS ')
ANDSdept<> ‘CS ' ; /*父查询块中的条件 */
例4.查询其他系中比计算机科学系所有学生年龄都小的学生姓名及年龄。
方法一:用ALL谓词
SELECTSname,Sage
FROM Student
WHERE Sage < ALL
(SELECT Sage
FROM Student
WHERE Sdept= 'CS ')
AND Sdept<> ' CS ’;
方法二:用聚集函数
SELECT Sname,Sage
FROM Student
WHERE Sage <
(SELECT MIN(Sage)
FROM Student
WHERE Sdept= 'CS ')
AND Sdept<>' CS ’;
>>谓词语义
ANY:任意一个
ALL:所有值
4)带有EXISTS谓词的子查询
例5.查询所有选修了1号课程的学生姓名。
解题思路:
本查询涉及Student和SC关系
Student中依次取每个元组的Sno值,用此值去检查SC关系
若SC中存在这样的元组,其Sno值等于此Student.Sno值,并且其Cno= '1',则取此Student.Sname送入结果关系
SELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno= ' 1')
>>说明:
1.EXISTS谓词——存在量词
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
若内层查询结果非空,则外层的WHERE子句返回真值
若内层查询结果为空,则外层的WHERE子句返回假值
由EXISTS引出的子查询,其目标列表达式通常都用* ,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义
2.NOT EXISTS谓词
若内层查询结果非空,则外层的WHERE子句返回假值
若内层查询结果为空,则外层的WHERE子句返回真值
例6:查询没有选修1号课程的学生姓名。
SELECT Sname
FROM Student
WHERE NOT EXISTS
(SELECT *
&nb