上一篇文章讲到连接查询,连接查询就是一个一个去查找相匹配的行,再返回给用户看。当我们数据量少的时候我们用连接查询没有太大问题,可是,当数据量大的时候,连接查询效率显然不高。这个时候我们可以用嵌套查询,可以提高查询效率。
还是上一个例子:查询和学号为“131101”的学生同系的学生信息。
我们可以先在xs表中通过学号“131101”,很容易查找到该同学的系为“计算机”,就确定了一个范围,利用该范围,就可以查找到与学号“131101”相同的系的所有学生。
概念:主查询(父查询或外层查询)和子查询(内层查询)。
1.子查询包含在主查询中,一般都用小括号括起来。
2.我们执行的时候,是先执行子查询,再将查询出来的结果返回给外部查询的where作为条件,一层一层往外执行的。
3.子查询,查询到的结果可选择部分出现在条件比较运算符的右边,并且可以有选择地跟在in,any(some),all和exists等谓词后面。注意:这里的any不是任一而是某一。
4.在包含相关子查询(也称为重复子查询)的查询中,子查询依靠外部查询获得值。
相关子查询:先逐行扫描外部查询的每一行,让其和内部查询的表进行对比,满足了查询where条件的返回真,不满足的返回假。如果只是单独执行内部查询是会报错的。
和(非相关)子查询的区别:(1)非相关子查询是内层查询执行完毕之后,将值传递给外部查询,再执行外部查询。
(2)相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。并且是外部先查询一次,然后再执行一次内部查询,由于其执行的次数多,效率并不是很高,可以用存储过程来代替。使用的最多的就是exists语句
5.子查询除了可以用在select语句里面,还可以用在insert、update以及delete语句当中。
例题:删除电子专业的所有学生的借阅记录。
分析:我们可以看到电子专业的名叫王一的同学有过借阅记录。
首先因为我们要删除的是电子专业的学生的借阅记录,所以,我们外层查询的条件一定是“电子”专业,然后我们内层查询要查询到有借阅记录的学生。
怎么查询有借阅记录的学生呢?我们可以将xs表和jy表连接起来,如果jy表中的借书证号和xs中的借书证号相等,那么,说明xs表中的该学生在jy表中有借阅记录。这样我们很容易就写出了内层查询。
-->in子查询
要注意的是,使用in和not in子查询的话,只能返回一列数据。
也就是说,从子查询传过来的只能是一列值,不能有多个列,所以,子查询里面不能使用通配符“*”,并且子查询中的select后面只有一个列。
-->比较子查询
问题:查询student表非计算机系中比计算机系某一个学生年龄小的学生姓名和年龄。
分析:先找到student表中非计算机系的学生的最大年龄,再和非计算机系学生年龄进行比较,只要有这样的一条记录,就说明有一个非计算机系的学生的年龄比计算机系的某一个学生的年龄小。(如果比最大的年龄小,说明就有一条记录了)再返回所有的记录即可。
方法一:
如果此时,我们使用in子查询的话,只能返回一系列列值,而无法进行比较,所以,我们需要使用比较子查询。
父查询和子查询之间用比较运算符进行关联。
方法二:由于这里我们返回的不是某一列,而是一个年龄的集合,所以我们不能直接用比较运算符,因为你不能将一个年龄和多个年龄进行对比。any代表某一,在oracle中也可以使用some。