EXISTS子查询问题

qq_39088116 2018-10-30 08:56:52
今天SQL Server课讲到**带有EXISTS运算符的子查询**
第一段的简介是:
**存在性子查询使用EXISTS运算符,EXISTS子查询并不返回任何数据,只产生逻辑值TRUE或FALSE。由于存在性子查询只是检测是否存在符合条件的记录,因此不需要列出具体的列名,选择列几乎都由(*)组成**
给出的语法是:

```
WHERE [NOT] EXISTS(subquery)
```
给出的例子是:
**查询所有选修了SQL SERVER课程的学生的学号,课程号,课程名和成绩,代码如下**

```
USE CJGL
GO
SELECT 学号,scoreinfo.课程号,课程名,成绩
FROM scoreinfo,classinfo
WHERE scoreinfo.课程号=classinfo.课程号
AND
EXISTS(SELECT * FROM CLASSINFO WHERE 课程名='SQL Server')
```
给出的结果是

```
学号 课程号 课程名 成绩
----------- ---------- -------------------- ------
980003 001 SQL Server 67
980007 001 SQL Server 78
```
这个应该是书上想要这段代码得出的结果,不过我们自己输入这段代码得出的结果是

```
学号 课程号 课程名 成绩
----------- ---------- -------------------- ------
980003 001 SQL Server 67
980004 002 Delphi 87
980005 003 Java程序设计 55
980006 002 Delphi 67
980007 001 SQL Server 78
980001 002 Delphi 88
980002 003 Java程序设计 78
980004 003 Java程序设计 86

```
老师说课本上的例子错了,然后又重新写了一个方法查到书上想要我们得到的结果。不过我感觉书上给的写法不应该完全是错的,我就以书上的写法为基础改了又改,想找到EXISTS子查询的规律。
我发现以这样的方式写,主查询条件不变的情况下总是能得到想要的结果

```
USE CJGL
SELECT 学号,scoreinfo.课程号,课程名,成绩
FROM scoreinfo,classinfo
WHERE scoreinfo.课程号=classinfo.课程号
AND EXISTS(SELECT * WHERE 课程名='SQL Server')
```
跟书上的不同是EXISTS子查询语句里 *SELECT * 后不加 **FROM classinfo** 就能得到想要的结果。但是不明白为什么会这样。
因为如果按书上说的,EXISTS子查询不返回数据,只返回逻辑值FALSE和TRUE,那感觉EXISTS语句的存在根本没什么意义
因为**主查询条件不变**的情况下,如果EXISTS的返回值为**FALSE**,那么整个查询就无数据返回,比如

```
USE CJGL
SELECT 学号,scoreinfo.课程号,课程名,成绩
FROM scoreinfo,classinfo
WHERE scoreinfo.课程号=classinfo.课程号
AND EXISTS(SELECT * FROM CLASSINFO WHERE 1<>1)
```

如果EXISTS的返回值为TRUE,那么就会把所有符合主查询的值返回,但并不是我们想得到的结果,比如:

```
USE CJGL
SELECT 学号,scoreinfo.课程号,课程名,成绩
FROM scoreinfo,classinfo
WHERE scoreinfo.课程号=classinfo.课程号
AND EXISTS(SELECT * FROM CLASSINFO WHERE 1=1)
```
我得出结论**EXISTS子查询不返回数据,只返回逻辑值FALSE和TRUE,返回值为TRUE则输出数据,返回值为FALSE则不输出数据**这句描述是不对的,也许是对的,但绝对是片面的。要么一行记录都不输出,要么输出的记录只符合主查询的条件,这样EXISTS子查询就没有存在的意义了。
然后在百度上找了好多跟EXISTS子查询语句有关的文章跟回答。发现了一个**关键**的知识点,EXISTS子查询分**关联子查询**和**非关联子查询**
大概意思是:
**EXISTS关联子查询是把符合主查询条件的记录再根据子查询的条件再次判断,如果子查询的返回值为TRUE,也就是符合子查询条件,那么输出此行记录**
**EXISTS非关联子查询是子查询是独立的,可以跟外部查询没有任何关系,只是用来返回逻辑值TRUE 或者 FALSE**
然后我得出结论**EXISTS非关联子查询只执行一次,返回的逻辑值适用于所有符合外部查询的记录,要么所有都是TRUE要么所有都是FALSE,因此对外部查询得出的记录是没有二次筛选的效果的。**
这也印证了**EXISTS子查询不返回数据,只返回逻辑值FALSE和TRUE,返回值为TRUE则输出数据,返回值为FALSE则不输出数据**这句话是片面的。
根据上面得出的结论我又用不同的查询条件做了几次实验,得出的结果都是跟预期相符的。
但是还有一个问题,EXISTS怎么样用才是关联子查询,怎么样用是非关联的子查询。
我发现这个例子中,**如果把子查询中的 **FROM TABLE_NAME**删去,总能实现对外部查询结果的二次筛选**
```
SELECT * WHERE 课程名='SQL Server'
```
**如果加上FROM TABLE_NAME,就成了一个输出判断,要么输出所有,要么一条记录也不输出。**

不过总感觉没有FROM TABLE_NAME的SELECT语句怪怪的,我猜测可能是**跟外部查询是个连个表链接查询有关,语句是默认对外部查询得出的临时表进行关联子查询**。


**刚开始学SQL Server,还是有点云里雾里,我对EXISTS子查询语句的理解大概是这样,今天上午上课讲的,到晚上才找到对结果合理的解释,搞得我一天茶饭不思。要是有理解的不对的地方希望前辈们指点一二!!!**
第一次发言,不太会弄格式~~~
...全文
84 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

11,849

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 非技术版
社区管理员
  • 非技术版社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧