Oracle数据库的嵌套查询

Oracle数据库的嵌套查询备注 此博客为转载 方便自己学习 Oracle 的嵌套查询 原作者地址请点击此处在前面 2 个章节 我们比较详细的介绍了一些 SQL 语句的基本用法 但是在我们实际的项目开发中 其实很多时候这些基本的用法远远不能满足我们项目的需求 这个时候就需要我们的嵌套查询 在 SQL 语句中 一个 select from where 语句称为一耳光查询快 将一个查询快嵌套在另外一个的 where 子句或 having 短语的条件

备注:此博客为转载,方便自己学习 Oracle的嵌套查询,原作者地址请点击此处

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

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

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

select Sname --------------外查询语句块------- from Student where Sno in --------------外查询语句块------- ( --------------内查询语句块------- select Sno From Sc where Cno=2 --------------内查询语句块------- ); 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

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

一。带有in谓词的子查询

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

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

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

①确定“XiaoHong”所在的系

select sdept from student where sname='XiaoHong' 
 
  • 1
  • 2
  • 3

得到的结果是:CS。

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

select sno,sname,sdept from student where sdept='CS'; 
 
  • 1
  • 2
  • 3

③合并操作。

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

select sno,sname,sdept from student where sdept in (   select sdept   from student   where sname='XiaoHong' ); 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

得到的结果也是一样。

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

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

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

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

【例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'        ) ); 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

代替方法:

select student.sno,sname from student,sc,course where course.cname='Math' and course.cno=sc.cno and sc.sno=student.sno; 
 
  • 1
  • 2
  • 3
  • 4

结果也是一样滴。

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

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

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

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

如下:

select sno,sname,sdept from student where sdept = (   select sdept   from student   where sname='XiaoHong' ); 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

----------------错误写法--------------------- select sno,sname,sdept from student where (   select sdept   from student   where sname='XiaoHong') =sdept; ----------------错误写法--------------------- 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

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

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

select sno,cno from sc x where grade>= (     select avg(grade)     from sc y     where y.     sno=x.sno); 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

执行过程可能如下:

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

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

得到结果是98.5

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

select sno,cno from sc x where Grade>=98.5; 
 
  • 1
  • 2
  • 3

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

select sname,sage from student where sage < any ( select sage from student where sdept='CS' ) and sdept <> 'CS'; -- 注意这是父查询的条件 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

数据库执行执行此查询的时候,首先处理子查询,找出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' 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

这里写图片描述

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

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

select sname,sage from student where sage <all ( select sage from student where sdept='CS' ) and sdept<> 'CS'; 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

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

select sname,sage from student where sage < ( select min(sage) from student where sdept='CS' ) and Sdept !='CS'; 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

select sname from student where exists ( select * from sc where Sno=Student.Sno and Cno=1 ) 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

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

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

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

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

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

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

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

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

select sname from student where not exists ( select * from sc where Sno=Student.Sno and Cno=1 ) 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/176709.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午9:15
下一篇 2026年3月26日 下午9:15


相关推荐

  • jar中没有主清单属性啥意思啊_java没有主清单属性

    jar中没有主清单属性啥意思啊_java没有主清单属性在pom文件中,添加如下即可&lt;plugin&gt;&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;&lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;…

    2025年9月15日
    7
  • java中array的方法_array java

    java中array的方法_array java题目要求为:卡拉兹(Callatz)猜想:对任何一个自然数n,如果它是偶数,那么把它砍掉一半;如果它是奇数,那么把(3n+1)砍掉一半。这样一直反复砍下去,最后一定在某一步得到n=1。当我们验证卡拉兹猜想的时候,为了避免重复计算,可以记录下递推过程中遇到的每一个数。例如对n=3进行验证的时候,我们需要计算3、5、8、4、2、1,则当我们对n=5、8、4、2进行验证的时候,就可以直接判定卡拉兹猜想的…

    2026年2月1日
    5
  • 40 道基础Dubbo 面试题及答案

    40 道基础Dubbo 面试题及答案转载自史上最全40道Dubbo面试题及答案,看完碾压面试官想往高处走,怎么能不懂Dubbo?Dubbo是国内最出名的分布式服务框架,也是Java程序员必备的必会的框架之一。Dubbo更是中高级面试过程中经常会问的技术,无论你是否用过,你都必须熟悉。下面我为大家准备了一些Dubbo常见的的面试题,一些是我经常问别人的,一些是我过去面试遇到的一些问题,总结给大家,希…

    2022年5月10日
    50
  • python 元类编程_Python进阶

    python 元类编程_Python进阶前言通常我们创建类都是使用class类名,但是小伙伴们有没有想过,类是由谁来创建的呢,python中常说的万物皆对象,对象是由类创建的,那类本身也可以看做是对象,类可以由元类type创建type

    2022年7月31日
    9
  • Java数组初始化数值

    Java数组初始化数值初始化变量 publicstatic String args int numbers newint 8 实际上 上面的代码的目的就是做了一个数组的初始化 这个初始化的作用就是开辟了该长度的存储空间 这个概念我们经常会混淆 这里还是希望大家有个印象 数组初始化完后 并没有存储实际的值 int 类型的数据默认值是 0 所以如果没有完成数组的赋值 那么 int 数组的每一个值都是 0 String 类型的数据默认值是 null 所以没有赋值 那么 Stri

    2025年11月12日
    5
  • 几个不知道算不算经典的游戏

    几个不知道算不算经典的游戏=600)window.open(http://www.gamestop.com/common/images/lbox/645357b.jpg);”src=”http://www.gamestop.com/common/images/lbox/645357b.jpg”onload=”if(this.width>600)this.width=600;”twffan=”done”

    2022年6月5日
    24

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号