在光標基礎(1)中,主要講述了什麼是光標,什麼是服務器光標,什麼是客戶光標。我們還把光標比作手,它的作用就是定位某條記錄。
光標沒有手那樣靈活,而且要復雜的多。根據不同的需要,光標被劃分為靜態光標( Static ),鍵集光標( KeySet),動態光標( Dynamic ),前向光標( Forward-only )。在文章最後還要介紹有關默認結果集的概念。
1. 靜態光標
靜態光標為查詢結果生成一個臨時的拷貝並存儲在 tempdb 中,你對結果集的所有操作,其實質是在一個私有的,臨時的數據拷貝上進行的,這個結果集的成員是固定的,別人對基表所作的任何修改都不會實時的反映出來。
采用靜態光標在服務器中創建臨時表是要付出代價的。我們知道 tempdb 經常用於復雜的數據檢索,如果結果集太大就會影響數據查詢的效率。
2. 鍵集光標
與靜態光標不同的就是鍵集光標只在 tempdb 中存儲唯一標識結果集各行的關鍵值 -- 鍵集(比如:索引)。
假設我們要查詢這樣的語句 "SELECT Cust_name FROM customers WHERE cust_id > 100",假定用戶101,200,300符合查詢條件。此後,每一次提取操作都會使用這些鍵值。換句話就是說,以後的 .Movenext 操作使服務器重新以鍵集為基礎進行查找,即:"SELECT Cust_name FROM customers WHERE cust_id IN(101,200,300)"。即使其他人輸入了用戶400,它也不會出現在結果集中。而基於鍵集所作的修改是可以看到的。
對於鍵集光標,要求該光標用到的表都應有一個唯一索引,如果不滿足這個條件,該光標會轉換成靜態光標。
3. 動態光標
在這種光標中,SELECT 語句在每次提取記錄時都要執行一次。與鍵集光標不同,它執行的是原 SELECT 語句,即:"SELECT Cust_name FROM customers WHERE cust_id > 100"。這就意味著動態光標的成員是不固定的,你在光標內所作的修改,或者其他人所作的修改,都會在下一次提取時反映出來。
說句題外話,有好多人問:為什麼RecordSet.RecordCount 返回 -1?(-1 代表不知道有多少條記錄,)其實好好想一下,不難得出結論。靜態光標和鍵集光標的成員是固定的,自然可以知道到底有多少條記錄,而動態光標卻相反,它不可能返回一個隨時變化的值。
4. 前向光標
顧名思義,只向前滾動的光標。這是 ADO 的缺省光標,通常從頭到尾進行數據處理,即只沿著一個方向,所以每一行不會被重新提取。前向光標是最快的光標。
5. 默認的結果集
默認結果集就是那些未以光標形式返回的結果集。
它的另一個名稱是 'firehose' ,這個詞更形象的反映了默認結果集的工作方式:只要客戶端不斷的處理返回的記錄,使網絡緩沖區有空間發送更多的結果,那麼服務器就會向客戶端繼續發出記錄。客戶端不向服務器發出請求,服務器僅是不斷的向網絡發送數據。
盡管我們把默認結果集看作是前向 / 只讀的光標,但這僅僅是一種稱呼,它確實同真正的光標不一樣。我們可以使用光標這個詞,但應明確:從 SQL Server 的角度來看,默認結果集不是一個光標,它不涉及服務器的光標服務。
默認結果集的效率通常比光標高。