EXISTS代表存在量词 。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。
例如:三个表:
student(sno,sname,ssex,sage,sdept)(学号,姓名,性别,年龄,专业)
course(cno,cname,cpno,ccredit)(课程号,课程名,选修课号,学分)
sc(sno,cno,grade)(学号,课程号,成绩)
1、 查询所有选修了1号课程的学生姓名。
本题涉及student和sc表。可以在student中一次取得每个元组的sno值,用此值去检查sc表。若sc表存在这样的元组,其sno值等于此student.sno值,并且其cno='1',则取此student.sname送入结果表。将此想法写成sql语句是:
select sname from student
where exists (
select *
from sc
where sno=student.sno and cno='1'
);
使用存在量词exists后,若内层查询结果非空,则外层的where子句返回真值,否则返回假值。由于exists引出的子查询,其目标列表达式通常用*,因为带exists的子查询只返回真值或假值,给出列名无实际意义。
本例中子查询的查询条件依赖于外层父查询的某个属性值(在本例中是student的sno值),因此也是相关子查询。这个相关子查询的处理过程是:首先取外层查询中(student)表的第一个元组,根据它与内层查询相关的属性值(sno值)处理内层查询,若where子句返回值为真,则取外层查询中该元组的sname放入结果表;然后再取(student)表的下一个元组;重复这一过程,直至外层(student)表全部检查完为止。
与exists谓词相对应的是not exists谓词。使用存在量词not exists后,若内层查询结果为空,则外层的where子句返回真值,否则返回假值。
2、查询没有选修1号课程的学生姓名
select sname from student
where not exists (
select * from sc sno=student.sno and cno='1'
);
一些带exists或not exists 谓词的子查询不能被其他形式的子查询等价替换,但所有带in谓词、比较运算符、any和all谓词的子查询都能用带exists谓词的子查询等价替换。
由于带EXISTS量词的相关子查询只关心内层查询是否有返回值,并不需要查具体值,因此其效率并不一定低于不相关子查询,有时是高效的方法。
SQL中没有全称量词
SQL中也没有蕴含逻辑运算,可以用谓词演算将其转换为:
1、查询选修了全部课程的学生姓名
2、查询至少选修了学生95002选修的全部课程的学生号码
1、没有全称量词,将其转换为等价的用存在量词的形式:查询这样的学生,没有一门课是他不选的。
select sname
from student
where not exists(
select *
from course
where not exist(
select *
from sc
where sc.sno = student.sno
and cno = course.cno
)
)
2、本查询用逻辑蕴含表达:查询学号为x的学生,对所有的课程y,只要95002学生选了课程y,则x也选了y。形式化表示如下
用p表示:学生95002选了课程y
用q表示:学生x选了课程y
转换为等价形式:
它表示的语义为:不存在这样的课程y,学生95002选了,而学生x没有选,sql如下:
select distinct sno
from sc scx
where not exists(
select *
from sc scy
where sno='95002'
and not exist(
select *
from scz
where scz.sno = scx.sno
and scz.cno=scy.cno))
1.用EXISTS/NOT EXISTS实现全称量词
SQL语言中没有全称量词"(For all),可以把带有全称量词的谓词转换为等价的带有存在量词的谓词:
" (x)PÛØ ($x(P)) :含义 " (x)P表示个体域里的所有个体都有性质P。Ø ($x(P)) 表示不存在着个体域中的个体没有性质P。
例 查询选修了全部课程的学生姓名。
SELECTSname
FROM Student
WHERE NOT EXISTS
(SELECT *
FROM Course
WHERE NOT EXISTS
(SELECT *
FROM SC
WHERE Sno= Student.Sno
AND Cno= Course.Cno);
2.用EXISTS/NOT EXISTS实现逻辑蕴函
SQL语言中没有蕴函(Implication)逻辑运算可以利用谓词演算将逻辑蕴函谓词等价转换为:
p®qÛØp∨q
例 查询至少选修了学生95002选修的全部课程的学生号码。
解题思路:
用逻辑蕴函表达:查询学号为x的学生,对所有的课程y,只要95002学生选修了课程y,则x也选修了y。
形式化表示:
用P表示谓词 “学生95002选修了课程y”
用q表示谓词 “学生x选修了课程y”
则上述查询为:" (y) p® q
等价变换:
" (y) p® qÛØ ($y (Ø (p®q ))
ÛØ ($y (Ø(Øp∨ q))
ÛØ$y(p∧Øq)
变换后语义:不存在这样的课程y,学生95002选修了y,而学生x没有选。
用NOT EXISTS谓词表示:
SELECT DISTINCTSno
FROM SC SCX
WHERE NOT EXISTS
(SELECT *
FROM SC SCY
WHERE SCY.Sno = ' 95002 ' AND
NOT EXISTS
(SELECT *
FROM SC SCZ
WHERESCZ.Sno=SCX.Sno AND
SCZ.Cno=SCY.Cno));