登陆注册
31848700000012

第12章 Oracle数据库基础——SQL语言(7)

5.4.3 嵌套查询——子查询

子查询是嵌套在其他SQL语句中的SELECT语句,也称嵌套查询。一般情况,子查询出现在SELECT 语句的WHERE子句中,也可以出现在FROM子句和HAVING子句中。子查询使用的原则如下:

一个子查询必须用括号括起来。

一个子查询必须出现在运算符的右边。

子查询可以在许多SQL语句中使用,如SELECT、INSERT、UPDATE、DELETE语句中。

子查询中不能包含ORDER BY 子句。在一个SELECT语句中只能有一个ORDER BY子句,假如要指定ORDER BY子句,该ORDER BY子句必须是主查询语句中的最后一个子句。

5.4.3.1 不相关的子查询

查询条件不依赖于父查询的子查询称为不相关子查询。

不相关子查询的执行过程为:先执行子查询,子查询只执行一次,子查询的结果作为父查询的条件。子查询的查询条件不依赖父查询,子查询可以独立执行。

不相关子查询的特点如下:

子查询能独立运行,子查询的条件不依赖父查询。

子查询只运行一次。

先执行子查询,后执行父查询。

1.带有IN谓词的子查询

在嵌套查询中,如果子查询的结果是一个集合,则必须用IN谓词联结子查询。与IN谓词对应的是NOT IN。

例5-106 查询与“吴晨”在同一个系学习的学生的学号、姓名、所在的系。

查询“吴晨”所在的系是一个子查询,查询学生的学号、姓名、系是主查询。由于可能有多个名为“吴晨”的同学,所以子查询的结果是一个集合。用IN谓词联结子查询。

上述查询的执行过程是:先执行内查询,得到“吴晨”所在的系的集合,然后将该集合作为外查询的条件,执行外查询。

本查询也可以用联结查询来实现。

先从course表中查询课程名称为MATHS的课程编号,再从sc表中查询选修了该课程编号的学生编号,最后从student表中查询该学生编号所对应的姓名。也可用下列语句实现。

2.带ANY谓词的子查询

带ANY谓词的子查询的一般格式如下:

<表达式><比较运算符>ANY<子查询结果集>

例5-108 查询有一门课程成绩等于95分的学生学号和姓名。

SQL>SELECT sno,sname

FROM student

WHERE sno ANY

(SELECT sno

FROM sc

WHERE grade 95);

例5-109 查询其他系中比信息系某一学生年龄小的学生姓名和年龄。

SQL>SELECT Sname,age

FROM student

WHERE age<ANY

(SELECT age

FROM student

WHERE dept″IS″)

AND dept<>′IS′

ORDER BY age DESC

3.带ALL谓词的子查询

带ALL谓词的子查询的一般格式如下:

<表达式><比较运算符>ALL<子查询结果集>

例5-110 查询所有课程成绩均大于90分的学生学号和姓名。

SQL>SELECT sno,sn

FROM student s

WHERE 90<ALL

(SELECT grade

FROM sc

WHERE s.snosc.sno);

例5-111 查询比所有女同学年龄大的男同学的学号和姓名。

SQL>SELECT s1.sno,s1.sname

FROM student s1

WHERE ***′M′

AND age>ALL

(SELECT s2.age

FROM student s2

WHERE ***′F′)

4.带有比较运算符的子查询

使用ANY或ALL谓词前必须使用比较运算符。

带有比较运算符的子查询是指父查询与子查询之间用比较运算符进行联结。当用户能确切知道子查询返回的是单值时,可以用>、<、>、<,或<>等比较运算符替代IN。

例5-112 查询选修课程名为“信息系统”的学生学号和姓名。

SQL>SELECT sno,sname

FROM student

WHERE sno IN

(SELECT sno

FROM sc

WHERE cno in

(SELECT cno

FROM course

WHERE cname′信息系统′))

例5-113 查询选修c2课程的学生学号和姓名。

SQL>SELECT sno,sname

FROM student

WHERE sno in

(SELECT sno

FROM sc

WHERE cno′c2′);

或者写成如下格式:

SQL>SELECT sno,sname

FROM student

WHERE sno any

(SELECT sno

FROM sc

WHERE cno′c2′);

例5-114 查询没选修c2课程的学生学号和姓名。

SQL>SELECT sno,sname

FROM student

WHERE sno not in

(SELECT sno

FROM sc

WHERE cno′c2′);

或者写成如下格式:

SQL>SELECT sno,sname

FROM student

WHERE sno<>all

(SELECT sno

FROM sc

WHERE cno′c2′);

例5-115 查询其他系中比信息系某一学生年龄小的学生姓名和年龄。

SQL>SELECT sname,age

FROM student

WHERE dept<>′IS′

AND age<any(SELECT age

FROM student

WHERE dept′IS′)

或者用集合函数改写成如下格式:

SQL>SELECT sname,age

FROM student

WHERE dept<>′IS′

AND age<(SELECT max(age)

FROM student

WHERE dept′IS′)

例5-116 查询其他系中比信息系所有学生年龄都小的学生姓名和年龄。

SQL>SELECT sname,age

FROM student

WHERE dept<>′IS′

AND age<all(SELECT age

FROM student

WHERE dept′IS′)

或者用集合函数改写成如下格式:

SQL>SELECT sname,age

FROM student

WHERE dept<>′IS′

AND age<(SELECT min(age)

FROM student

WHERE dept′IS′)

上述查询执行时,先执行子查询,然后根据子查询的结果执行父查询。查询涉及多个表时,用嵌套查询逐步求解,层次清楚,具有结构化程序设计的优点。

5.4.3.2 相关子查询

查询条件依赖于外层父查询的某个属性值的子查询为相关子查询。

相关子查询的执行过程是:首先取外层查询中表1的第1个元组,根据它与内层查询相关的属性值处理内层查询,若WHERE子句的子查询返回真,则取此元组放入结果表中,然后取外层查询中表1的下一个元组,重复上述过程,直到外层查询中表1全部检索完为止。

相关子查询的特点如下:

子查询不能独立运行,依赖于父查询中取的值。

子查询需多次运行。

先执行外层的主查询,后执行内层的子查询。

1.带有EXISTS谓词的子查询

EXISTS代表存在量词。带有EXISTS谓词的子查询不返回任何实际数据,它只产生逻辑真值“true”或逻辑假值“false”。若内层子查询结果非空,则外层主查询的WHERE后的条件为真,否则为假。

由EXISTS引出的子查询(即相关子查询),其目标列表达式通常都用*(最好用常量),这样执行效率比较高。因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义。

与EXISTS对应的是NOT EXISTS谓词。

例5-117 查询所有选修C1号课程的学生姓名。

SQL>SELECT sname

FROM student

WHERE EX ISTS

(SELECT*

FROM sc

WHERE snostudent.sno

AND cno′C1′);

执行过程是:首先找外层查询中student表的第一行,根据它的sno值处理内层子查询,若子查询结果非空,则exists为真,就把student表的第一行的sname值取出放入查询结果的结果集中;然后找student表的第二行、第三行……重复上述过程,直到student表中所有行均被检索过为止。

例5-122 检索所学课程包含学生S3所学全部课程的学生学号(相当于查询学号X,对所有课程Y,只要S3选修了课程Y,则学生X也选修课程Y)。

SQL>SELECT distinct x.sno

FROM sc as x

WHE RE not exists

(SELECT′x′

FROM sc as y

WHERE y.sno′s3′and not exists

(SELECT′x′

FROM sc as z

WHERE x.snoz.sno and z.cnoy.cno));

5.4.3.3 其他子句中的子查询

上述不相关子查询和相关子查询介绍的,都是在SELECT语句的WHERE子句中使用子查询的例子,在其他DML语句和SELECT语句的其他子句中也都可以使用子查询。

1.FROM 子句中的子查询

子查询可以出现在SELECT语句的FROM子句中,与定义和使用视图很类似。FROM子句中的子查询用括号括起来,并且可以给其取一个别名。

例5-123 查询每个部门的平均工资,并且找出每个部门中的每一个雇员的工资与其所在部门的平均工资的差。

SQL>SELECT e.deptno,e.ename,e.sal salary,a.average,

e.sal-a.average difference

FROM emp e,(SELECT deptno,avg(sal)average

FROM emp

GROUP BY deptno)a

WHERE e.deptnoa.deptno

ORDER BY 1,2

2.HAVING 子句中的子查询

HAVING 子句中也可以使用子查询,Oracle服务器先执行子查询,然后将子查询的结果返回给主查询的HAVING 子句。

例5-124 查询emp表中平均工资超过30号部门平均工资的部门信息。

SQL>SELECT deptno,avg(sal)

FROM emp

GROUP BY deptno

HAVING avg(sal)>

(SELECT avg(sal)

FROM emp

WHERE deptno30)

例5-125 查询平均工资最低的job。

SQL>SELECT job,age(sal)

FROM emp

GROUP BY job

HAVING avg(sal)

(SELECT min(avg(sal))

FROM emp

GROUP BY job)

3.多表查询时的子查询

子查询可作为关系运算中的一部分,也可以查询多个表的信息。

例5-126 在纽约的雇员中,查询工资高于scott的雇员(假设在emp表中只有一个scott)。

SQL>SELECT ename,job,sal

FROM emp,dept

WHERE loc′net york′

AND emp.deptnodept.deptno

AND sal>(SELECT sal

FROM emp

WHERE ename′scott′)

如果需要找出在纽约的雇员中,工资高于在DALLAS工作的scott的雇员(假如公司中有不止一个scott),语句如下。

SQL>SELECT ename,job,sal

FROM emp,dept

WHERE loc′new york′

AND emp.deptnodept.detpno

AND sal>(SELECT sal

FROM emp,dept

WHERE ename′scott′

AND loc′nallas′

AND emp.deptnodept.deptno)

4.其他DML语句中的子查询

例5-127 用相关子查询实现将所有雇员的工资改成相应部门的最大工资。

SQL>UPDATE emp

SET sal(SELECT max(sal)

FROM emp e

WHERE e.deptnoemp.deptno)

例5-128 用相关子查询实现删除工资低于该部门平均工资的雇员记录。

SQL>DELETE FROM emp e

WHERE sal<(SELECT avg(sal)FROM emp

WHERE deptnoe.deptno)

例5-129 用子查询往表中插入记录。

SQL>INSERT INTO emp

SELECT*FROM oldemp

也可以在INSERT语句的VALUES子句中指定子查询。

SQL>INSERT INTO dept

VALUES((SELECT max(deptno)+10 FROM dept),′education′,′beijing′)

例5-130 使用带聚组函数的子查询来实现查询最早受雇的雇员。

SQL>SELECT ename,hiredate

FROM emp

WHERE hiredate

(SELECT min(hiredate)

FROM emp)

注意:可以在INSERT、UPDATE、DELETE语句中使用一个子查询替代表名。例如:

SQL>DELETE FROM(SELECT*FROM dept WHERE deptno<20)WHERE deptno10;

5.4.4 集合查询

每一个SELECT语句都能获得一个或一组元组。若要把多个SELECT语句的结果合并为一个结果集,可用集合操作来完成。集合操作主要包括并操作UNION、交操作INTERSECT和差操作MINUS。运算结果集的结构与第一个查询结果的结构一样。

需要注意的是,参加UNION、INTERSECT、MINUS操作的各查询结果集中的数据项数目必须相同;对应项的数据类型也必须相同。各个查询结果中的列名可以不同。

5.4.4.1 集合的并运算

集合的并运算(UNION)将多个查询结果合并起来,形成一个完整的查询结果时,系统会自动去掉重复的元组。

例5-131 查询计算机科学系的学生或年龄不大于19岁的学生。

SQL>SELECT*

FROM student

WHERE dept′CS′

UNION

SELECT*

FROM student

WHERE age<19

5.4.4.2 集合的交运算

集合的交操作(INTERSECT)是将多个查询结果中的公共元组形成一个完整的查询结果。

例5-132 查询计算机系并且年龄不大于19岁的学生。(即查询计算机系的学生与年龄不大于19岁的学生的交集。)

SQL>SELECT*

FROM student

WHERE dept′CS′

INTERSECT

SELECT*

FROM student

WHERE age<19

或者可以写成如下格式:

SQL>SELECT*

FROM student

WHERE dept′CS′

AND age<19

5.4.4.3 集合的差运算

集合的差操作(MINUS)就是将属于第一个查询结果而不属于其他查询结果的元组形成一个完整的查询结果。

例5-133 查询计算机系并且年龄大于19岁的学生。(即查询计算机系的学生与年龄不大于19岁的学生的差集。)

SQL>SELECT*

FROM student

WHERE dept′CS′

MINUS

SELECT*

FROM student

WHERE age<19

或者写成如下格式:

SQL>SELECT*

FROM student

WHERE dept′CS′

AND age>19

5.4.5 视图的查询

视图定义后,用户可以像对基本表那样对视图进行查询。

同类推荐
  • 信息革命

    信息革命

    随着经济社会的快速发展,电子产品走进了千家万户,与电子产品相伴的信息技术也已渗透到人们生产生活的方方面面。加强信息技术普及,已成为业内人士的共识。鉴于此,在有关部门的大力支持下,经过认真筹划,我们编辑出版了《信息革命》一书。该书以时间为经,在记述信息技术发展历程的同时,深入浅出地介绍了信息技术的相关知识,对人们更好地利用现代信息技术服务经济社会建设和个人生产生活必将产生积极作用。本书由李大东主编。
  • 虚拟现实:下一个产业浪潮之巅(第2版)

    虚拟现实:下一个产业浪潮之巅(第2版)

    毫无疑问,虚拟现实时代已经来临,VR不仅将彻底改变人们交互的方式。而且会是互联网的下一个风口,VR会创造新时代,即由人的体验构成的互联网时代。目前,全球范围众多的科技、影视等商业巨头纷纷砸巨资押注VR产业。例如,扎克伯格越来越坚定地认为,VR将会成为下一代计算机平台;任正非在内部讲话中也提到,华为要保持理性地进行VR投入与研究,要在这个充满诱惑的领域里分得一杯羹,谁最后倒下,谁便赢得天下。本书是作者基于VR行业多年的研究以及创立VR公司的经验写成,目的是让读者快速、全面地了解VR产业最新、最重要的信息,如生态链、技术瓶颈、发展前景以及人才结构等,是一部不可多得的VR行业入门读物。
  • 无人机:知道这些就够了

    无人机:知道这些就够了

    不久的将来无人机将像智能手机一样司空见惯,而你对无人机的了解有多少?你知道无人机有哪些用途吗?无人机对你和你的家庭又会产生什么样的影响呢?知道这些就够了。
  • 数据库原理及Oracle应用

    数据库原理及Oracle应用

    进入21世纪,随着国家信息化步伐的加快及各行业信息化进程的不断加速,社会对专业(非计算机专业)人才的信息技术能力要求越来越高。为了适应社会对专业人才的要求,全国各高校在重视专业知识培养的同时也非常注重计算机应用能力的训练,即信息技术能力的培养。计算机应用水平已成为衡量高校毕业生综合素质的突出标志之一。
  • 云计算、网络安全和网络盗窃:网络世界防盗初学指南

    云计算、网络安全和网络盗窃:网络世界防盗初学指南

    网络犯罪层出不穷,保护自己的安全,防止受到攻击,似乎是一个艰巨的任务。幸运的是,有一些人人都能采取的措施,可以降低成为网络袭击对象的风险。保证基于云计算程序的安全和降低被袭击的风险,关键在于理解云安全的共同责任。云提供商需要全力确保实施尽可能严格的安全策略。
热门推荐
  • 天行

    天行

    号称“北辰骑神”的天才玩家以自创的“牧马冲锋流”战术击败了国服第一弓手北冥雪,被誉为天纵战榜第一骑士的他,却受到小人排挤,最终离开了效力已久的银狐俱乐部。是沉沦,还是再次崛起?恰逢其时,月恒集团第四款游戏“天行”正式上线,虚拟世界再起风云!
  • 天行

    天行

    号称“北辰骑神”的天才玩家以自创的“牧马冲锋流”战术击败了国服第一弓手北冥雪,被誉为天纵战榜第一骑士的他,却受到小人排挤,最终离开了效力已久的银狐俱乐部。是沉沦,还是再次崛起?恰逢其时,月恒集团第四款游戏“天行”正式上线,虚拟世界再起风云!
  • 六界之门

    六界之门

    千载后,天将倾,地将陷,黑暗笼罩人间。尸山血海,群魔乱舞,福兮?祸兮?湮灭?辉煌?人界、冥界、妖界、仙界、天界、魔界并存,大劫将至,六界动荡。一少年身怀神秘青莲,凝聚九窍金丹,闯兰若寺、入锁妖塔、登诛仙台,一路行来,桩桩古今秘史在其面前揭开。亲情、爱情、友情,皆愿以性命守护!且看夏言踏足六界,登顶巅峰!(PS:本书书友群正式开启,530538304,邀诸位道友来此一聚!)
  • 奇才足球

    奇才足球

    几千年以后,人类文明经过不断毁灭又重建,各国决定用足球比赛代替战争,四年一度的全球杯大赛是决定全球资源分配的重大赛事。随着足球赛事蓬勃发展,逐渐有球员觉醒了超越常人的能力,这些超能力被称为奇才。在这奇才足球的时代,一群少年用热血青春铸就传奇荣光。(作者伪球迷,你们就当超能力足球小将看好了。还有我不会写感情戏,所以无女主。)
  • 咸鱼翻身之我是富二代

    咸鱼翻身之我是富二代

    “儿子,我拿了块地!”“什么?快递?谁订的?咱家都揭不开锅了您还订快递,下午还有份兼职要做,明儿把工资给您打过去,有时候也吃好点,挂了啊。”“喂?喂喂?怎么挂了,放桌上?”说着,凡仁他爸便把一份地契放在了桌上,嘴角露出一丝莫名的微笑。
  • 超十星进化

    超十星进化

    时空裂缝开启,大星际时代降临!星环少的人没前途?幸好方运拥有不断升级进化的天赋。你的初级剑道升级十星达成,进化为中级剑道,并领悟万钧剑意,你的剑变得超强,一剑破万法。你的炼体术升级十星达成,进化为圣血霸体。你的黑铁级星技束缚升级十星达成,进化为青铜级星技六丈光牢,并觉醒星魂美杜莎,超凶,瞪谁谁石化。人类进入时空裂缝,神秘的庇护所,无数强大的星兽,辉煌璀璨的新纪元,精彩纷呈的斑斓故事,彻底拉开了序幕。这一切,都要从一颗黑球开始说起……***轻松搞笑,欢迎入坑。***
  • 大话芝麻官

    大话芝麻官

    “大人,我一进去就看见来福在暴打常伟!”“那他是用什么打的常伟呢?”“他用他那沙包大的拳头一拳一拳的打在常伟身上!”包星星张了张嘴,看了看来福空荡荡的右边衣袖,又看了看来福吊在脖子上包的严严实实的左手。“本大人觉得这个事情没那么简单啊……”
  • 她和他的电影

    她和他的电影

    每个人都有属于自己的青春,每个人都有属于自己的爱情。在爱情与现实的十字路口,每个人都会作出不同的选择,把握住弥足珍贵的爱情,亦或是向现实狠狠的低头。选择不同,结局也各不相同。不管怎样,青春都是道靓丽的风景线,无论风景是美丽,是凄迷,是甜蜜,是疼痛。。。。。
  • 冷血公主与冰山王子的爱情故事

    冷血公主与冰山王子的爱情故事

    一位冷血到底的女孩为了帮自己的父母报仇而走上一条复仇之路,在开始计划这复仇计划时候,遇上了一位弱小得女生,女孩就开始同情上了她,保护着她,然而出现了3位美男子,而她们会擦出怎样的火花呢???
  • 她是友还是敌

    她是友还是敌

    有一对双胞胎,进了一所最好的学校,进了学校里最好的班级,班级里有一名班花。班花成绩优异,还是老师的得力助手,自从双胞胎来了以后,占了班花的位置。在经历过许多事以后,班花时而变成双胞胎的朋友,又时而变成双胞胎的敌人。双胞胎不知她到底是友还是敌……敬请期待。