VB6基本資料庫應用(七):多重條件搜尋
同系列的第七篇,上一篇在:http://blog.csdn.net/jiluoxingren/article/details/48402835
多重條件搜尋
前文再續,書接上一回。很高興又能說出這句話了。
第五章講述了條件查詢。事實上SQL:Select語句的Where子句並不只是能接受一個條件。舉個實際應用的慄(例)子,如果有重名,那麼按姓名去查詢,就會出現多個結果,為了唯一確定一個人,我們還可以再提供需要查詢的人的手機號碼,一般而言這樣就唯一確定一個人了。
為此,我們在資料庫新增一個手機號碼欄位。開啟資料庫,然後在表的【設計檢視】中,再新增一個欄位,命名為【PhoneNo】。由於手機號碼也有11位的長度,所以還是設定資料型別為【雙精度型】,如下圖所示。
然後回到【資料表檢視】(在【設計檢視】和【資料表檢視】之間切換有更快捷的方法。就是在欄位名稱上面的那個Student那裡,單擊滑鼠右鍵,最下面會有選擇進入什麼檢視)。手工修改一下資料。修改好的資料如下所示:
StudentID |
StudentName |
PhoneNo |
123456 |
林則徐 |
13888080088 |
562893 |
葉劍英 |
13920171101 |
662356 |
黃飛鴻 |
13427103456 |
785714 |
黃飛鴻 |
13978569013 |
電話號碼都是隨便亂編的。不過可以看到,有兩個“黃飛鴻”,不過學號和電話都不一樣。這樣只按第五章所說的,給出條件WHERE StudentName=’黃飛鴻’去查詢,結果就會有兩個了。
為了繼續講下去,還是必須要先講一下邏輯連線詞。什麼是邏輯連線詞呢?我們經常會這樣說話:“姓名是黃飛鴻,而且電話號碼是13978569013 的人”,這裡姓名和電話號碼是兩個條件,用“而且”兩個字連線起來,“而且”就是邏輯連線詞。
在SQL中,使用“與”(AND),“或”(OR),“非”(NOT)三個邏輯連線詞來連線多個條件。前面的“而且”相當於是“與”(AND)。
例如“姓名是黃飛鴻,而且電話號碼是13978569013 的人”,SQL語句可以寫成:
SELECT * FROM Student WHERE StudentName=’黃飛鴻’ AND PhoneNo=13978569013
邏輯連線詞的結合性
WHERE後面不僅能接兩個條件,還可以接多個條件,而且邏輯連線詞也不要求整一個語句都是用同一個連線詞。但是,如果有多個不同的連線詞,如何理解就會出現問題。例如:
SELECT * FROM Student WHERE StudentName=’黃飛鴻’ AND PhoneNo=13978569013 OR PhoneNo=13888080088
為了突出一些,我讓每個條件顯示成不同的顏色。這條語句的條件翻譯成中文是這樣說的“學生名是黃飛鴻,且電話號碼是13978569013,或電話號碼是13888080088”。這樣問題來了,這句話可以有兩種理解:
1. (學生名是黃飛鴻,且電話號碼是13978569013),或者是電話號碼是13888080088的任何一個人【不論名字】
2. 學生名是黃飛鴻,(且電話號碼是13978569013,或者是電話號碼是13888080088)【姓名一定要黃飛鴻,電話是這兩個之一就行,有其他的不要】
為了檢驗我們的理解那一種是正確的。啟動Access(圖示的版本是2013)。在【建立】選單單擊【查詢設計】,如下圖所示。
彈出來的一個對話方塊直接關掉,然後單擊一下介面左上角的SQL,就可以將查詢切換到【SQL檢視】
將上面的SQL語句複製貼上進去。注意,單引號要手工改一下,改成英文半形的單引號。文章這裡我雖然是用英文半形輸入,但是最後顯示的還是中文的單引號。中文符號是不行的!!
然後單擊左上角的執行之後結果就出來了,如下圖所示。
觀察Student表的資料可以知道,電話號碼是13888080088的人名叫林則徐。而查詢的結果中也包含了林則徐。這就證明第一種理解是正確。由此我們可以得出結論:
SQL中的多個邏輯連線詞總是從左往右運算的(左結合性)。
所以(StudentName=’黃飛鴻’ AND PhoneNo=13978569013)構成一個整體,然後再附加一個OR PhoneNo =13888080088。前面的給出了唯一的結果,即上圖的第二條記錄。然後PhoneNo =13888080088確定了第一條,名字是林則徐的記錄。
而且需要注意的是,結果記錄集的排序與查詢的條件無關。以後我會講到按照某個欄位的升序或降序進行排序。同樣也是在SQL:Select中完成的。
在SQL語句中,括號可以改變運算的順序,如果你真的要SQL是按照第二種理解執行的話,可以加上括號(英文半形括號):
SELECT * FROM Student WHERE StudentName=’黃飛鴻’ AND (PhoneNo=13978569013 ORPhoneNo=13888080088)
執行的結果只有一條,就是上圖中的第二條記錄。
“非”(NOT)邏輯連線詞
這個邏輯連線詞出現的頻率極高。他可以搭配其他的邏輯連線詞使用,而且只對出現在其右邊的一個條件起作用。例如:
SELECT * FROM Student WHERE NOT StudentName='黃飛鴻' AND PhoneNo=13888080088
本來“非“(NOT)邏輯連線詞的加入,也會使語句在人理解的時候出現歧義,但是經過實驗,NOT只對右邊的一個條件起作用。實驗的方式也是跟上面一樣的,在Access裡執行一下語句看看結果即可。也就是說,上面這條語句的條件是“姓名不是黃飛鴻,並且電話號碼是13888080088的人”。所以這條語句的結果就是上圖的第一條記錄,林則徐的那條,因為13888080088是林則徐的電話號碼,而且姓名“林則徐”也滿足“姓名不是黃飛鴻”的條件。
同樣的,如果你希望讓NOT作用與多個條件,就要加上括號:
SELECT * FROM Student WHERE NOT (StudentName='黃飛鴻' AND PhoneNo=13888080088)
加上括號之後的結果是這樣的,如下圖所示。沒錯,全部都出來了。你能想明白為什麼嗎?
這也是一個需要注意的問題,在布林代數(數學)中,這樣的結果稱為德摩根定理:
1. NOT( a AND b) 等價於 (NOT a) OR(NOT b)
2. NOT( a OR b) 等價於 (NOT a) AND (NOT b)
這兩條結論稱為德摩根定理。其中的a,b可以是任意的條件。根據德摩根定理,上面的結果就很容易理解了
NOT (StudentName='黃飛鴻' AND PhoneNo=13888080088)
等價於
(NOT StudentName='黃飛鴻') OR (NOT PhoneNo=13888080088)
名字不是黃飛鴻的有林則徐,葉劍英。電話號碼不是13888080088(對應名字是林則徐)的有兩個黃飛鴻,還有葉劍英。中間用OR連線,那當然是全都出來了。其實直接理解也是可以的,名字是黃飛鴻,電話號碼是13888080088的人是沒有的,所以結果是空的,最後NOT一下,空的相反就是全部了。
所以,如果要給NOT加括號,那就要想清楚了。
接著,我們來寫一下程式碼檢查一下,介面當然是要修改一下的,增加一個ListBox來顯示電話號碼,修改好的介面如下所示。
由於目前我用來用去都是SQL:Select語句,所以我不說,大家也應該知道怎麼做了吧。新的測試只需要將RecordSet物件的Open方法的第一個引數換成相應的SQL語句即可。不過因為改變了介面,所以我還是貼出全部的程式碼以供參考。這份程式碼只檢驗了語句SELECT* FROM Student WHERE StudentName=’黃飛鴻’ AND PhoneNo=13978569013 OR PhoneNo =13888080088的結果。
VB程式碼開始:
Dim Cnn As ADODB.Connection
Dim rec As ADODB.Recordset
Private Sub Form_Load()
'建立新的Connection物件
Set Cnn= New ADODB.Connection
'注意要記住該資料庫目錄為你資料庫檔案當前的位置
Cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=E:\Sample.mdb;PersistSecurity Info=False"
'建立新的Recordset物件
Set rec= New ADODB.Recordset
'開啟student表的全部欄位的全部內容
'adOpenKeyset, adLockOptimistic。鍵集遊標和開放式鎖。
'單純為了讀取資料應該使用只進遊標和只讀鎖。
'但是為了方便就統一使用鍵集遊標和開放式鎖了
'詳細參見第十章
rec.Open "SELECT * FROM Student WHERE StudentName='黃飛鴻' AND PhoneNo=13978569013 OR PhoneNo =13888080088", Cnn, adOpenKeyset, adLockOptimistic
'資料的提取
Do Until rec.EOF = True
List1.AddItem rec.Fields("StudentID").Value
'Fields物件,括號裡的是索引(Index),索引填寫的內容為欄位的名稱
'Item屬性是Fields物件的預設屬性,他的一個引數就是Index
'Fields("Student")表示一個Field物件
'Fields("Student")等價於
'rec.Fields.Item("Student")或
'rec.Fields!("Student")
'!表示預設屬性
List2.AddItem rec.Fields("StudentName").Value
List3.AddItem rec.Fields("PhoneNo").Value
'移動下一條記錄為當前記錄
rec.MoveNext
Loop
End Sub
VB程式碼結束
在這裡羅列出這一章所給出的SQL語句,讀者自己把它們放到Open方法的第一個引數中,執行一下程式,結果跟上面再Access中執行SQL的結果是一樣的,就不再截圖了。
本章相關的SQL語句:
1. SELECT * FROM Student WHERE StudentName=’黃飛鴻’ AND PhoneNo=13978569013 OR PhoneNo =13888080088
2. SELECT * FROM Student WHERE StudentName=’黃飛鴻’ AND (PhoneNo=13978569013 OR PhoneNo =13888080088)
3. SELECT * FROM Student WHERE NOT StudentName='黃飛鴻' AND PhoneNo=13888080088
4. SELECT * FROM Student WHERE NOT (StudentName='黃飛鴻' AND PhoneNo=13888080088)
那麼長時間不寫教程,開始的時候還真找不到感覺,不知道自己要說什麼,怎麼說,真是慚愧。感覺到後面才漸漸回來了。才發現原來多重條件查詢自己能說出那麼多東西,於是把第五章最後修改了一下,這一章標題也修改了一下,只說多重條件查詢。模糊查詢和基於範圍的查詢之後再講。
下一章,我將來講述模糊搜尋與基於範圍的搜尋,敬請期待。本套教程未完,待續。