登陆注册
18668900000012

第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 sex′M′

AND age>ALL

(SELECT s2.age

FROM student s2

WHERE sex′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 视图的查询

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

同类推荐
  • 网络知识

    网络知识

    一般地说,将分散的多台计算机、终端和外部设备用通信线路互联起来,彼此间实现互相通信,并且计算机的硬件、软件和数据资源大家都可以共同使用,实现资源共享的整个系统就是计算机网络。
  • 小型局域网组建与维护

    小型局域网组建与维护

    本书以组建和维护小型局域网为主线,面向实际工程应用,按照项目化课程模式的要求组织编排。全书共分8个项目,主要包括认识计算机网络一概述、绘制小型网络拓扑图、连接网络一传输介质、连接网络一联网设备、认识计算机网络一网络协议、连接网络一网络寻址、组建小型交换网络——配置交换机、连接互联网——配置宽带路由器。每个项目都有明确的工作目标、工作任务、实现过程和知识点分析,力求集教、学、做于一体,从而更好地激发学生的学习兴趣,培养学生的动手能力。
  • 学校计算机实用技术

    学校计算机实用技术

    本书由杭州市上城区教育学院编著,他们邀请了众多信息技术教育教学的一线专家,认真细致地筛选了学校计算机应用方面的常见问题,提出了解决问题的具体操作方案,旨在帮助一线教育工作者解决可能面临的种种问题,为广大教师提供便捷服务。
  • 三维动画审美谈

    三维动画审美谈

    数字时代,美的标准充满更多的不确定性。而三维动画以数字图像形式成为这个图时代的代表。三维动画及三维图像不仅仅是由于应用了仿真数字图像技术而带来的虚拟空间,还有更多的是由三维图像技术所引发或引导的被扩展的图像技术,这些技术无不应用在现代视觉设计领域的各个方面,并且,由此引起社会的追热,引起审美观念的改变。这些改变是在进行中的,变化中的,也是在发展中的。对于未知的美,我们做的只是追寻和记录,我们不知道以后的美将会是什么样,尽管我们苦苦追寻,孜孜探讨,同时也在默默审视。我们在追寻中享受美,在探讨中认知美,在审视中体验美……
  • 大话设计模式

    大话设计模式

    本书主要采用JAVA语言介绍设计模式中比较常见的23种设计模式,分29章具体介绍,以现实生活中常见的事情为例来具体分析讲解。
热门推荐
  • 邪王追妻:腹黑神医废材妃

    邪王追妻:腹黑神医废材妃

    雨,不知谁心落,不知谁心碎。夜铭一声,女子悠悠的在冰冷的地面上爬了起来。雨,冲刷了血水,刻下了印记。孰能知?二世的轮回,一次次痛于心铭的印记,早已无法卸去。孰能知?绝世的容颜上,烙下的是爱恨的鞭痕,早已痛彻心扉。孰能知?魅人的双眸中,早已不是天真的眸神,而是悔恨和痛。
  • 游龙戏凤

    游龙戏凤

    林珊上辈子没考上公务员,穿越后竟让当上了女驸马。那个……中饱私囊一下,应该没什么问题吧?什么!那个人是太子!?殿下,臣知错了……
  • 乱世神征

    乱世神征

    青玉案乱世神征深青堰碎空飞絮,琼楼破,世如洗。云翻陆转道难砌,金征天下,社稷流舛。孰为八荒主?烟火登穹彩千缕,一绽天外芳华去。人生循法若傀戏。长生安有?东风黄土,只听后人忆。
  • 混天魔王

    混天魔王

    学校的混世魔王葛小七家中房子倒塌了,他从废墟中捡到一支笔。从此,呼风唤雨无所不能。
  • 我的朋友女

    我的朋友女

    一场关于青春的疯狂剧一首与爱情有关的交响曲一回正面跟现实生活的拳拳碰击一个屌丝的成长记
  • 绝世王妃之修炼记

    绝世王妃之修炼记

    当二货、撒娇的女主角,遇上高冷的男主男。他们会摩擦出这样热烈的火花。开始女追男进行时。女主角:莫妍云男主角:冷陌(男强女强)文章中女主角一个16岁的高一女学生穿越到了一个没有历史记载的世界——火云大陆。女主角:火木水三系(炼药师)男主角:风雷冰三系(驯兽师)
  • 铁骑踏苍穹

    铁骑踏苍穹

    是上天的宠幸儿还是手中的棋子?亦能跳出棋盘?为了亲人、为了兄弟、为了女人,少年的他不仅付出万倍的汗血,还随时付出生命!面对困难,不逃避!建学院、设军团、夺神器、斩天道、成永生为了活下去,继续冲下去。。。。。。
  • 收破烂的全能高手

    收破烂的全能高手

    无所不知的陆回本是一个普普通通的大学生,却因为一次意外得到神奇的力量开启了他的潜能!平时是个学生,有时又回去收破烂赚钱,有时确是绝世高手...也是泡妞高手
  • 欢喜冤家:吃醋王爷萌宠妃

    欢喜冤家:吃醋王爷萌宠妃

    现代商业王国的继承人,意外穿越到了古代,什么,穿越地点是乱葬岗?好吧,她忍!可是穿成婴儿是怎么回事!身世成谜吗?装傻卖萌,她会!斗智斗勇她也会!收服傲娇王爷什么的更没有问题,赚钱发家致富,斗智指点江山,华丽丽得穿越就来个华丽丽的人生吧!来听听男主候选人的发言。男主:“待我君临天下,许你四海为家”男二:“待我一袭袈裟,许你相思放下”男二:“待我青丝白发,许你浪迹天涯”男二:……王爷怒,将她锁在怀里:“你这么多男二,你家男主知道吗?”说到底,这是一代平民王妃步步为营到执掌天下的故事。
  • 战仙斗佛

    战仙斗佛

    佛无所不知,无所不在,心存世间万物,洞悉世间一切!以无私成就大私!却要以杀戮祭祀,浴血重生,在痛苦中诞生!