准備數據
我們先介紹下使用的3個數據表:
student數據表:
course數據表:
sc數據表:
EXISTS
EXISTS代表存在量詞∃。帶有EXISTS謂詞的子查詢不返回任何數據,只產生邏輯真值“true”或者邏輯假值“false”。
一個例子1.1:
要求:查詢選修了課程”操作系統“的同學
SQL語句:
- SELECT Sname FROM student
- WHERE EXISTS
- (SELECT * FROM sc,course WHERE Sno=student.Sno AND sc.Cno=course.Cno AND course.Cname="操作系統")
SELECT Sname FROM student WHERE EXISTS (SELECT * FROM sc,course WHERE Sno=student.Sno AND sc.Cno=course.Cno AND course.Cname="操作系統")
使用存在量詞EXISTS后,若內層查詢結果為非空,則外層的WHERE子句返回值為真,否則返回值為假。
在本例中,首先分析最內層的語句:
- SELECT * FROM sc,course WHERE Sno=student.Sno AND sc.Cno=course.Cno AND course.Cname="操作系統"
SELECT * FROM sc,course WHERE Sno=student.Sno AND sc.Cno=course.Cno AND course.Cname="操作系統"
本例中的子查詢的查詢條件依賴於外層父查詢的某個屬性值(本例中的是Student的Sno值),這個相關子查詢的處理過程是:
首先取外層查詢中(student)表的第一個元組,根據它與內層查詢相關的屬性值(Sno值)處理內層查詢,若外層的WHERE返回為真,則取外層查詢中該元組的Sname放入結果表;
然后再取(student)表的下一組,重復這一過程,直至外層(Student)表全部檢查完畢。
查詢結果表:
NOT EXISTS
與EXISTS謂詞相對的是NOT EXISTS謂詞。使用存在量詞NOT EXISTS后,若對應查詢結果為空,則外層的WHERE子語句返回值為真值,否則返回假值。
例子2.1:
要求:查詢沒有選修課程”操作系統“的同學
SQL語句:
- SELECT Sname FROM student
- WHERE NOT EXISTS
- (SELECT * FROM sc,course WHERE Sno=student.Sno AND sc.Cno=course.Cno AND course.Cname="操作系統")
SELECT Sname FROM student WHERE NOT EXISTS (SELECT * FROM sc,course WHERE Sno=student.Sno AND sc.Cno=course.Cno AND course.Cname="操作系統")
使用NOT EXISTS之后,若內層查詢結果為非空,則對應的NOT EXISTS不成立,所以對應的WHERE語句也不成立。
在例子1.1中李勇同學對應的記錄符合內層的select語句的,所以返回該記錄數據,但是對應的NOT EXISTS不成立,WHERE語句也不成立,表示這不是我們要查詢的數據。
查詢結果表:
例子2.2(這是一個用NOT EXISTS表示全稱量詞的例子):
要求:查詢選修了全部課程的學生姓名。
SQL語句:
- SELECT Sname
- FROM Student
- WHERE NOT EXISTS
- (SELECT * FROM Course WHERE NOT EXISTS
- (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno)
- );
SELECT Sname FROM Student WHERE NOT EXISTS (SELECT * FROM Course WHERE NOT EXISTS (SELECT * FROM SC WHERE Sno=Student.Sno AND Cno=Course.Cno) );
這個算是一個比較復雜的sql語句了,兩個EXISTS和三個WHERE。
這個sql語句可以分為3層,最外層語句,最內層語句,中間層語句。
我們很關心最外層語句,因為結果表中的數據都是最外層的查詢的表中的數據,我們更關心最內層的數據,因為最內層的數據包含了全部的判斷語句,決定了student表中的那一條記錄是我們查詢的記錄。
我們由內而外進行分析:
最外層的student表中的第一條記錄是李勇同學對應的記錄,然后中間層的course表的第一條記錄是數據庫對應的記錄,然后對該數據進行判斷(最內層的WHERE語句),結果返回真,則內層的NOT EXISTS為假,
然后繼續對course表中的下一條記錄進行判斷,返現NOT EXISTS的值也為假,直到遍歷完course表中的所有的數據,內層的NOT EXISTS的值一直都是假,所以中間層的WHERE語句的值也一直都是假。
對應student的李勇記錄,course表中的所有的記錄對應的中間層的返回值為假,所以最外層的NOT EXISTS對應的值為真,最外層的WHERE的值也為真,則李勇對應的記錄符合查詢條件,裝入結果表中。
然后繼續對student表中的下一條記錄進行判斷,直達student表中的所有數據都遍歷完畢。
查詢結果表: