#查询选修了二号课程的学生的姓名 SELECT Sname #外层查询 / 父查询 FROM Student WHERE Sno IN ( SELECT Sno #内层查询 / 子查询 FROM SC WHERE Cno='2' );
注意: ORDER BY子句不允许出现在内层查询中, 因为其是对最终结果集的操作.
嵌套查询基本规则/定义:
上层查询块被称为外层查询 / 父查询;
下层查询块被称为内层查询 / 子查询;
SQL语言允许多层嵌套查询;
子查询中不允许使用ORDER BY子句;
嵌套查询可分为两类: 不相关子查询 与 相关子查询.
不相关子查询:
子查询的查询条件不依赖于父查询
步骤:
由里向外逐层处理.
每个子查询在上一级查询处理之前求解.
子查询的结果用于建立父查询的查找条件.
相关子查询:
子查询的查询条件依赖于父查询
步骤:
取外层查询中表的第一个元组, 根据它与内层查询相关的属性值处理内层查询.
若WHERE子句返回值为真, 则取此元组放入结果表.
然后再取外层表的下一个元组, 重复这一过程, 直到外层表全部被检查完为止.
带有IN谓词的子查询
IN谓词表名集合之间的所属关系 如最上面的例子中, Sno属于子查询的结果集里的Sno.
例子1-1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#查询与刘晨在同一个系学习的学生学号, 姓名 SELECT Sno, Sname #第二步: 根据刘晨的系名查询所有学生的学号, 姓名 FROM Student WHERE Sdept IN ( #若这里Sdept确定只有唯一的值, 那么IN也可以用=代替,这涉及到带有比较运算符的子查询 SELECT Sdept #第一步: 确定刘晨所在系名 FROM Student WHERE Sname ='刘晨' ); #此查询为不相关子查询 #将上述例子转变为连接实现,而不是嵌套实现 SELECT S1.Sno, S1.Sname FROM Student S1, Student S2 WHERE S1.Sdept = S2.Sdept AND S2.Sname ='刘晨';
嵌套查询允许多重嵌套(理论上无限套娃):
例子1-2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#查询选修了课程名为"信息系统"的学生学号和姓名 SELECT Sno, Sname #第三步: 找出这些学号的学生名字 FROM Student WHERE Sno IN ( SELECT Sno #第二步: 找出选修该课程号学生的学号 FROM SC WHERE Cno IN ( SELECT Cno #第一步: 找出信息系统课程的课程号 FROM Course WHERE Cname ='信息系统' ) ); #此查询为不相关子查询 #将上述例子转变为连接实现,而不是嵌套实现 SELECT Student.Sno, Student.Sname FROM Student, SC, Course WHERE Student.Sno = SC.Sno AND SC.Cno = Course.Cno AND Course.Cname ='信息系统';
#查询所有选修了1号课程的学生姓名 SELECT Sname FROM Student WHEREEXISTS ( #子查询结果返回true或false SELECT* FROM SC WHERE SC.Sno = Student.Sno AND SC.Cno ='1'; ); #查询没有选修1号课程的学生姓名 SELECT Sname FROM Student WHERENOTEXISTS ( #子查询结果返回true或false SELECT* FROM SC WHERE SC.Sno = Student.Sno AND SC.Cno ='1'; );