sql子查询和嵌套查询
子查询和嵌套查询
标签:
it |
嵌套查询就是在外部还有一个查询。
子查询是在select 内部还有一个select 查询常常也被称为内查询
下面的错误示例:
select name from [user] where age <= (select age from [user] where id>1 )
子查询返回的值多于一个。当子查询跟随在 =、!=、<、<=、>、>= 之后,或子查询用作表达式时,这种情况是不允许的。
1.语法
子查询的句法如下:
(SELECT [ALL | DISTINCT]<select item list>
FROM <table list>
[WHERE<search condition>]
[GROUP BY <group item list>
[HAVING <group by search conditoon>]])
2.语法规则
(1)子查询的SELECT查询总使用圆括号括起来。
(2)不能包括COMPUTE或FOR BROWSE子句。
(3)如果同时指定TOP子句,则可能只包括ORDER BY 子句。
(4)子查询最多可以嵌套32层,个别查询可能会不支持32层嵌套。
(5)任何可以使用表达式的地方都可以使用子查询,只要它返回的是单个值。
(6)如果某个表只出现在子查询中而不出现在外部查询中,那么该表中的列就无法包含在输出中
3.语法格式
(1)WHERE 查询表达式 [NOT] IN(子查询)。
(2)WHERE 查询表达式 比较运算符 [ ANY | ALL ](子查询)。
(3)WHERE [NOT] EXISTS(子查询)。
SQL子查询一般作为WHERE子句或HAVING子句的一部分出现。在WHERE子句中,它们帮助选择在查询结果中呈现的各个记录。在HAVING子句中,它们版主选择在查询结果中呈现的记录组。
子查询和实际的SELECT语句之间的区别:
在常见的用法中,子查询必须生成一个数据字段作为它的查询结果。这意味着一个子查询在它的SELECT子句中几乎总是有一个选择项。
ORDER BY子句不能在子查询中指定,子查询结果被中查询在内部使用,对用户来说永远是不可见的,所以对它们进行排序没有一点意义。
呈现在子查询中的字段名可能引用主查询中表的字段。
在大多数实现中,字查询不能是几个不同的SELECT语句的UNION,它只允许一个SELECT。
子查询搜索条件
*子查询比较测试 = <> < <= > >=
(在这个类型的测试中,子查询必须产生一个合适数据类型的值,即,它必须产生一个查询结果记录,这个查询结果记录只包含一个字段。如果查询产生了多个记录
或多个字段,比较久没有意义了,SQL将报告一个错误。如果子查询不产生记录或产生一个NULL值,比较测试将返回NULL)。
*子查询组成员测试(IN)
*存在测试(EXISTS)
*限定性比较测试 ANY ALL
子查询和链接
子查询编写的许多查询也可以写成多表查询或连接。
HAVING查询中的子查询
当一个子查询呈现在HAVING子句中时,它是作为由HAVING子句执行的记录组选择的一部分工作的。
简单嵌套查询
嵌套查询内层子查询通常作为搜索条件的一部分呈现在WHERE或HAVING子句中。例如,把一个表达式的值和一个由子查询生成的一个值相比较,这个测试类似于简单比较测试。
子查询比较测试用到的运算符是:=、<>、<、>、<=、>=。子查询比较测试把一个表达式的值和由子查询的产生的一个值进行比较,返回比较结果为TRUE的记录。
带IN的嵌套查询
带IN的嵌套查询语法格式为:WHERE 查询表达式 IN(子查询)。
一些嵌套内层的子查询会产生一个值,也有一些子查询会返回一列值,即子查询不能返回带几行和几列数据的表。原因在于子查询的结果必须适合外层查询的语句。当子查询产生一系列值时,适合用带IN的嵌套查询。
use student
select *
from student
where 学号 in (select 学号 from grade )
带IN的内层嵌套还可以是多个值的列表。
例如,查询“年龄”是“22、21、24”的学生信息。SQL语句如下:
use student
select *
from student
where 年龄 in(21,22,24)
综上所述,当嵌套子查询中存NULL值,避免使用NOT IN
带NOT IN的嵌套查询
NOT IN的嵌套查询语法格式:WHERE 查询表达式 NOT IN(子查询)
NOT IN和IN的查询过程相类似。
select *
from course
where 课程代号 not in
(select 课程代号 from grade where 课程代号 is not null )
子查询存在NULL值时,避免使用NOT IN。因为当子查询的结果包括了NULL值的列表时,把NULL值当成一个未知数据,不会存在查询值不在列表中的记录。
use student
select *
from student
where 学号 not in
(select 学号 from grade
)
由于子查询的结果包括了NULL值,所以最终的查询结果只有空值。正确查询的SQL语句如下:
use student
select *
from student
where 学号 not in
(select 学号 from grade where 学号 is not null)
带SOME的嵌套查询
select *
from [user]
where age<some
(select avg(age) from [user])
SQL支持3种定量比较谓词:SOME、ANY和ALL。它们都是判断是否任何或全部返回值都满足搜索要求的。其中SOME和ANY谓词是存在量的,只注重是否有返回值满足搜索要求。这两种谓词含义相同,可以替换使用。
SOME是把每一行指定的列值与子查询的结果进行比较,如果哪行的比较结果为真,满足条件就返回该行。本实例的嵌套的子查询结果就是一个数值,然后“student”学生表的每一条记录的年龄列值与之相比较,满足就返回行。
带ANY的嵌套查询
ANY属于SQL支持的3种定量谓词之一。且和SOME完全等价,即能用SOME的地方完全可以使用ANY。
使用ANY解决上述示例。在查询分析器中输入的SQL语句如下:
use student
select *
from student
where 年龄<any
(select avg(年龄) from student)
SQL中定量谓词不支持反操作,也就是说,不能在ANY或者SOME前加NOT关键字。但可以用“<>”号表示否定
带ALL的嵌套查询
ALL谓词的使用方法和ANY或者SOME谓词一样,也是把列值与子查询结果进行比较,但是它不要求任意结果值的列值为真,而是要求所有列的查询结果都为真,否则就不返回行。
下面查询除了这些“课程代号”的课程信息,这些“课程代号”是指相应的“课程成绩”大于90分的“课程代号”。在查询分析器中输入的SQL语句如下:
use student
select *
from course
where 课程代号 <> all
(select 课程代号 from grade where 课程成绩>90)
SQL的这几个定量谓词,都可以使用6种比较运算符中的任何运算符
带EXISTS的嵌套查询
EXISTS谓词只注重子查询是否返回行。如果子查询返回一个或多个行,谓词返回为真值,否则为假。EXISTS搜索条件并不真正地使用子查询的结果。它仅仅测试子查询是否产生任何结果。
用带in的嵌套查询也可以用带EXISTS的嵌套查询改写。
下面把用带IN的嵌套查询写的例子改为用EXISTS书写的嵌套查询。在查询分析器中输入的SQL语句如下:
use student
select *
from student
where exists
(select 学号 from grade where student.学号=grade.学号 )
EXISTS谓词子查询中的SELECT子句中可使用任何列名,也可使用任意多个列,这种谓词只注重是否返回行,而不注重行的内容。用户可以规定任何列名或者只使用一个星号。例如上述例子的SQL语句和下面的SQL语句完全等价
select *
from student
where exists
(select * from grade where student.学号=grade.学号 )
NOT EXISTS的作用与EXISTS正相反。如果子查询没有返回行,则满足NOT EXISTS中的 WHERE子句。