EXISTS:查询有结果则返回真值,查询为空则返回false。
NOT EXISTS:查询有结果返回false,查询为空返回true。
假设现在有三张表:
student
course
sc
业务:查询选修了所有课程的学生姓名
思路:查询了所有选修课程的学生,那么即找到某一个学生中存在有一门没有选到的就排除该学生剩下的就是都选修课程的学生
执行语句:
-- 建表 create table student( sno char(4) primary key ); create table course( cno char(2) primary key ); create table sc( sno char(4), cno char(2), primary key (sno,cno) ); insert into student values (001); insert into student values (002); insert into course values ('a'); insert into course values ('b'); insert into course values ('c'); insert into sc values (001,'a'); insert into sc values (001,'b'); insert into sc values (002,'a'); insert into sc values (002,'b'); insert into sc values (002,'c'); --执行语句 SELECT Sno FROM Student WHERE NOT EXISTS (SELECT * FROM Course WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno) );
语句执行的具体过程:
具体思路:
1.要先找到某一个同学,看他所选的课程中是否全部包含course表中的课程,而sc表是选修了课程的学生才会被放进去,而且连接了student表和course表。因为一个表有很多个同学,每个同学又有很多课,所以就有了两层循环,最大那层循环(同学表)就在最外面,其次就是对应同学选的课的,最后一层是用来给两张表做校验的。所以就先找到一个同学,比如说1号,在sc表中先用student和sc共有的sno找到他和他对应的信息(包括他选修的课程)“SELECT * FROM SC WHERE Sno=Student.Sno” ; student循环会先传第一个元组(1号)进来第二个NOT EXISTS 的语句中
2.然后再看得出的目前1号学生所含有的课程中和course表中课程有没有对应不上的"SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno" 然后course里会传一个元组(a)进来,看sc中1号能和a匹配上的,就会留下,然后继续和b、c匹配,执行第二层course循环。匹配到c的时候发现1号并没有c这个课程则select *就选不出这个人,NOT EXISTS中就是空值,就返回TRUE,然后再返回给第二层的NOT EXISTS,第二层的NOT EXISTS检测到为TRUE(即有东西),就返回FALSE,所以1号不会被select name打印
3.2号也是如此