热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

跟我一起学Oracle11g【9】

前言在前面2个章节,我们比较详细的介绍了一些SQL语句的基本用法,但是在我们实际的项目开发中,其实很多时候这些基本的用法远远不能满足我们项目的需求,这个时候就需要我们的嵌套查询。在SQL语句中,一个select-from-where语句称为一耳光查询快。将一个

前言 在前面2个章节,我们比较详细的介绍了一些SQL语句的基本用法,但是在我们实际的项目开发中,其实很多时候这些基本的用法远远不能满足我们项目的需求,这个时候就需要我们的嵌套查询。 在SQL语句中,一个select-from-where语句称为一耳光查询快。将一个

前言

在前面2个章节,我们比较详细的介绍了一些SQL语句的基本用法,但是在我们实际的项目开发中,其实很多时候这些基本的用法远远不能满足我们项目的需求,这个时候就需要我们的嵌套查询。

在SQL语句中,一个select-from-where语句称为一耳光查询快。将一个查询快嵌套在另外一个的where子句或having 短语的条件的查询称为嵌套查询(Nested Query)。

比如,先举一个简单的例子:

select Sname  --------------外查询语句块------- 
from Student
where Sno in  --------------外查询语句块------- 
      (      --------------内查询语句块-------     
         select Sno
          From Sc
          where Cno=2
             --------------内查询语句块------- 
      );

查询语句块分为外查询语句或叫父查询以及内查询或子查询。

NOTE:SQL语言允许多层嵌套查询,即一个子查询中还可以嵌套其他子查询。需要特别指出的是,子查询的select语句中不能使用order by字句,order by 只能对最终查询结果排序。

一。带有in谓词的子查询

在嵌套查询中,子查询往往是一个集合,所以谓词in是嵌套查询中最经常使用的谓词。

【例1】查询与“XiaoHong”在同一个系的学生

OK,我们一步一步的来分解这个查询步骤:

①确定“XiaoHong”所在的系

select sdept
from student 
where sname='XiaoHong'

得到的结果是:CS。

②查找所有在CS系学习的所有学生

select sno,sname,sdept 
from student 
where sdept='CS';

ok,得到如下结果:

③合并操作。

现在我们只需要把上面的操作合并在一起就好了!

select sno,sname,sdept 
from student 
where sdept in 
(
  select sdept
  from student 
  where sname='XiaoHong'
);

得到的结果也是一样。

本例中,因为子查询的查询条件不依赖于父查询,所以称为不相关查询

当然本例中也还可以有其他解法:自连接方法如下:

select s1.sno,s1.sname,s1.sdept 
from student s1,student s2 
where s1.sdept=s2.sdept and s2.sname='XiaoHong';

可见,一个查询有很多种方法,当然不同的方法执行的效率可能会有很大的不同。

【例2】查询选修了课程名为”Math“的学生学号和姓名

看似这一句很短,其实这里有2个子查询。我们需要先弄清楚里面的关系,然后在来进行解答

思路如下:

1).课程名在course表中才有,所以我们从course表中选出课程名为Math的课程号(Cno)

2).选出课程号之后,在在SC表中,找到课程号所对应的学生号

3).在student表中找出对应的学号和学生名字。

select sno,sname   --第三步,最后从student表中取出数据出来。 
from student 
where sno in
(
     select sno --第二步。。找出SC关系表中的选修了2号课程的学生学号 
     from sc 
     where cno in
           (
               select cno     -- 第一步。。找出course表中的课程名为math的课程号。结果为2.
         from course 
         where cname='Math'
       )
);

结果如下:

代替方法:

select student.sno,sname from 
student,sc,course 
where course.cname='Math' 
and course.cno=sc.cno and sc.sno=student.sno;

结果也是一样滴。

二。带有比较运算符的子查询

带有比较运算符的子查询是指父查询之间用比较运算符进行连接。当用户能确切知道内存查询返回的是单&#20540;时,可以用>,<,>=,<=,!=,<>等等比较运算符。

【例3】和例1 是一样的:查询与“XiaoHong”在同一个系的学生

因为一个学生只可能在一个系学习,也就是说内查询的结果是一个&#20540;,因此可以用“=”代替“in”

如下:

select sno,sname,sdept 
from student 
where sdept =
(
  select sdept
  from student 
  where sname='XiaoHong'
);

这样 也能得到和例1的结果。

需要注意的是,子查询一定要跟在比较符之后,下面写法是错误的:

----------------错误写法---------------------
select sno,sname,sdept 
from student 
where 
(
  select sdept
  from student 
  where sname='XiaoHong') =sdept;
----------------错误写法---------------------

【例4】找出每个学生超过他选修课课程平均成绩的课程号

这个怎么理解呢?我们先把结果写出来,然后再来剖析它。

select sno,cno 
from sc x 
where grade>=
(
    select avg(grade) 
    from sc y 
    where y.
    sno=x.sno);

x是Sc表的别名,y也是一样。内存查询是求一个学生所有选修课程平均成绩,至于是哪个学生的平均成绩要看s.sno的&#20540;。,而该&#20540;是和父查询有关的,所以这类查询叫做相关子查询。

执行过程可能如下:

①从外层查询中取出SC表中的一行(也就是元组 x),将x的&#20540;sno

select avg(Grade) 
from sc y 
where y.sno=1;

得到结果是98.5

②执行内查询得到的结果是:98.5,所以得到外查询是:

select sno,cno 
from sc x 
where Grade>=98.5;

得到结果如下:

然后,外层查询取出下一个元组重复做上面的动作。。。

得到的结果是:

三。带有any(some)或all谓词的子查询

子查询返回单&#20540;可以用比较算术法,但是返回多&#20540;时要用any(有些系统用some)或者all谓词修饰符。而是用any或all谓词时则必须同时是用比较运算符。
>any 大于子查询结果中的某个&#20540;
>all 大于子查询结果中的所有&#20540;

>=any大于等于子查询结果中的某个&#20540;
<=any小于等于子查询结果中的某个&#20540;
>=all 大于等于子查询结果中的所有&#20540;
<=all 小于等于子查询结果中的所有&#20540;

=any 等于子查询结果中的中的某个&#20540;
=all 等于子查询结果中的所有&#20540;(通常没有实际意思)

!=(或<>)any 不等于子查询结果中的某个&#20540;
!=(或<>)all 不等于子查询结果中的的任何一个&#20540;

【例5】查询其他系中比计算机科学系某一个学生年龄小的学生姓名和年龄

SQL语句如下:

select sname,sage 
from student
where sage < any
(
    select sage 
        from student 
    where sdept='CS'
) and sdept <> 'CS'; -- 注意这是父查询的条件

数据库执行执行此查询的时候,首先处理子查询,找出CS系中所有学生的年龄,找出一个集合(18,22)。任何处理父查询,找出所有不是CS系并且年龄小于18或22的学生即可。

本查询也可以用聚集函数来实现。首先用子查询查出CS系中最大年龄(22),任何在父查询中找出所有非CS系并且年龄小于22岁的学生即可。

select sname,sage 
from student
where sage <
(
    select max(sage)
    from student
    where sdept='CS'
) and sdept<>'CS'

也可以得到上面的结构。结果如下:

【例6】查询其他系中比计算机科学系所有学生年龄都小的学生姓名和年龄

经过上面的分析,这个很简单,如下

select sname,sage 
from student
where sage 
(
    select sage
    from student
    where sdept='CS'
) and sdept<> 'CS';


这里需要向大家说声对不起,刚开始构建数据的时候,没有构建好,所以这里查询为空,为了试验的完整性,我这里修改一下数据结构。

update student set sage=17 where sname='XiaoZhang';

ok,我们现在在执行刚才的操作,可以得到如下结果。

本查询也可以使用聚集查询来实现,如下:

select sname,sage
from student
where sage <
(
    select min(sage)
    from student
    where sdept='CS'
) and Sdept !='CS';

事实上,聚集函数实现子查询通常比直接用all或any的效率更好。对应关系表如下:

= <>或!= < <= > >=
ANY IN == <=Max >Min >=Min
ALL == NOT IN <=Min <=Max
四。带有exists谓词的子查询

带有exists谓词的子查询不返回任何数据,只产生逻辑真或假,也就是true或false。

【例6】查询所有选修了1号课程的学生姓名

select sname 
from student
where exists
(
    select *
    from sc
    where Sno=Student.Sno and Cno=1
)

那上面的执行流程是怎么样的呢?

①从外查询student表中取出一行数据

②把这条数据的Sno和内查询Sc表中的Sno进行比较

③若比较结果为真,则把这数据的sname放入一个结果集合中。

④然后再取student表的吓一条数据,直到取完为止。

使用exists量词后,若内存结果非空,则外层的where字句返回真&#20540;,否则返回假&#20540;。

由于exists引出的子查询,起目标列表达式通常都是“*”,因为带有exists的子查询只返回true或false,给出列名无具体意思。

exists谓词相对应的是not exists。使用not exists后,如果内存查询结果为空,则外层的where字句返回真&#20540;,否则返回假&#20540;。

【例7】查询没有选修了1号课程的学生姓名

select sname 
from student
where not exists
(
    select *
    from sc
    where Sno=Student.Sno and Cno=1
)

一些带exists或not exists谓词的子查询不能被其他形式的子查询等价替换,但是其他带有in谓词、比较运算符、any、all谓词的子查询都能用exists谓词的子查询替换。


推荐阅读
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • Oracle分析函数first_value()和last_value()的用法及原理
    本文介绍了Oracle分析函数first_value()和last_value()的用法和原理,以及在查询销售记录日期和部门中的应用。通过示例和解释,详细说明了first_value()和last_value()的功能和不同之处。同时,对于last_value()的结果出现不一样的情况进行了解释,并提供了理解last_value()默认统计范围的方法。该文对于使用Oracle分析函数的开发人员和数据库管理员具有参考价值。 ... [详细]
  • MyBatis错题分析解析及注意事项
    本文对MyBatis的错题进行了分析和解析,同时介绍了使用MyBatis时需要注意的一些事项,如resultMap的使用、SqlSession和SqlSessionFactory的获取方式、动态SQL中的else元素和when元素的使用、resource属性和url属性的配置方式、typeAliases的使用方法等。同时还指出了在属性名与查询字段名不一致时需要使用resultMap进行结果映射,而不能使用resultType。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了通过mysql命令查看mysql的安装路径的方法,提供了相应的sql语句,并希望对读者有参考价值。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
author-avatar
manassatromble
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有