EXISTS 的子查询 不返回具体的数据,只返回所查询数据的行数。所以一般EXISTS后面的查询通常都用 * 表示,给出具体的列名没有实际意义
若内层的查询结果为非空,则外层的 WHERE语句 子句返回真值,否则返回假值
【例1】 查询所有选修1号课程的学生姓名
SELECT sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = '1')
它的执行顺序如下:
1、从Student表中取出一个元组
2、若在 SC 表中 存在sno的值等于 Student.sno 且 cno= '1' ,则能查到一行数据 ,where返回的值为真。
意味着 此条数据符合筛选要求,放入结果集;
3、取下一个元组 重复这一过程 进行数据的判断,直到把Student表中的所有元组检查完毕。最后把所有符合要求的数据返回
NOT EXISTS 的子查询 ,若内层的查询结果为非空,则外层的 WHERE语句 子句返回假值,否则返回真值
【例2】 查询没有选修1号课程的学生姓名
SELECT sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = '1')
【例3】查询选修全部课程的学生的姓名
SQL中不存在全称量词(for all),但是可以把带有全称量词的谓语转化为等价的带有存在量词的谓语
查询选修全部课程的学生的姓名 可以理解为 没有一门课程是他不选修的
SELECT sname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = Course.cno));
执行的顺序:
1、从Student表中取出一个元组
2、把这个元组放在后面的子查询进行判断
若这个学生选择了全部的课程,则对于Course中的任意一条数据,在第二个NOT EXISTS子查询中,
查询结果都非空,
NOT EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = Course.cno);
则返回值为假
SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = Course.cno);
查询结果返回值为真,则此条数据满足要求。此条数据保存到结果集
若这个学生没有选择了全部的课程,则对于Course中的任意一条数据,在第二个NOT EXISTS子查询中,
至少存在一条查询结果查询不到,
NOT EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = Course.cno);
则返回值为真
SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE sno = Student.sno AND cno = Course.cno);
查询结果返回值为假,则此条数据不满足要求。丢掉