1. 程式人生 > >資料庫中cursor遊標的概念

資料庫中cursor遊標的概念

遊標(cursor)

  遊標是系統為使用者開設的一個數據緩衝區,存放SQL語句的執行結果

  每個遊標區都有一個名字

  使用者可以用SQL語句逐一從遊標中獲取記錄,並賦給主變數,交由主語言進一步處理

  主語言是面向記錄的,一組主變數一次只能存放一條記錄

  僅使用主變數並不能完全滿足SQL語句嚮應用程式輸出資料的要求

  嵌入式SQL引入了遊標的概念,用來協調這兩種不同的處理方式

  在資料庫開發過程中,當你檢索的資料只是一條記錄時,你所編寫的事務語句程式碼往往使用SELECT INSERT 語句。但是我們常常會遇到這樣情況,即從某一結果集中逐一地讀取一條記錄。那麼如何解決這種問題呢?遊標為我們提供了一種極為優秀的解決方案。

  1.遊標和遊標的優點

  在資料庫中,遊標是一個十分重要的概念。遊標提供了一種對從表中檢索出的資料進行操作的靈活手段,就本質而言,遊標實際上是一種能從包括多條資料記錄的結果集中每次提取一條記錄的機制。遊標總是與一條SQL 選擇語句相關聯因為遊標由結果集(可以是零條、一條或由相關的選擇語句檢索出的多條記錄)和結果集中指向特定記錄的遊標位置組成。當決定對結果集進行處理時,必須宣告一個指向該結果集的遊標。如果曾經用 C 語言寫過對檔案進行處理的程式,那麼遊標就像您開啟檔案所得到的檔案控制代碼一樣,只要檔案開啟成功,該檔案控制代碼就可代表該檔案。對於遊標而言,其道理是相同的。可見遊標能夠實現按與傳統程式讀取平面檔案類似的方式處理來自基礎表的結果集,從而把表中資料以平面檔案的形式呈現給程式。

  我們知道關係資料庫管理系統實質是面向集合的,在MS SQL SERVER 中並沒有一種描述表中單一記錄的表達形式,除非使用where 子句來限制只有一條記錄被選中。因此我們必須藉助於遊標來進行面向單條記錄的資料處理。由此可見,遊標允許應用程式對查詢語句select 返回的行結果集中每一行進行相同或不同的操作,而不是一次對整個結果集進行同一種操作;它還提供對基於遊標位置而對錶中資料進行刪除或更新的能力;而且,正是遊標把作為面向集合的資料庫管理系統和麵向行的程式設計兩者聯絡起來,使兩個資料處理方式能夠進行溝通。

  2. 遊標種類

  MS SQL SERVER 支援三種類型的遊標:Transact_SQL 遊標,API 伺服器遊標和客戶遊標。

  (1) Transact_SQL 遊標

  Transact_SQL 遊標是由DECLARE CURSOR 語法定義、主要用在Transact_SQL 指令碼、儲存過程和觸發器中。Transact_SQL 遊標主要用在伺服器上,由從客戶端傳送給伺服器的Transact_SQL 語句或是批處理、儲存過程、觸發器中的Transact_SQL 進行管理。 Transact_SQL 遊標不支援提取資料塊或多行資料。

  (2) API 遊標

  API 遊標支援在OLE DB, ODBC 以及DB_library 中使用遊標函式,主要用在伺服器上。每一次客戶端應用程式呼叫API 遊標函式,MS SQL SEVER 的OLE DB 提供者、ODBC驅動器或DB_library 的動態連結庫(DLL) 都會將這些客戶請求傳送給伺服器以對API遊標進行處理。

  (3) 客戶遊標

  客戶遊標主要是當在客戶機上快取結果集時才使用。在客戶遊標中,有一個預設的結果集被用來在客戶機上快取整個結果集。客戶遊標僅支援靜態遊標而非動態遊標。由於伺服器遊標並不支援所有的Transact-SQL 語句或批處理,所以客戶遊標常常僅被用作伺服器遊標的輔助。因為在一般情況下,伺服器遊標能支援絕大多數的遊標操作。由於API 遊標和Transact-SQL 遊標使用在伺服器端,所以被稱為伺服器遊標,也被稱為後臺遊標,而客戶端遊標被稱為前臺遊標。在本章中我們主要講述伺服器(後臺)遊標

  遊標詳細說明:

  RS.OPEN SQL,CONN,A,B

  引數A為設定遊標的型別,其取值為:

  0 僅向前遊標,只能向前瀏覽記錄,不支援分頁、Recordset、BookMark

  1 鍵集遊標,其他使用者對記錄說做的修改將反映到記錄集中,但其他使用者增加或刪除記錄不會反映到記錄集中。支援分頁、Recordset、BookMark

  2 動態遊標功能最強,但耗資源也最多。使用者對記錄說做的修改,增加或刪除記錄都將反映到記錄集中。支援全功能瀏覽。

  3 靜態遊標,只是資料的一個快照,使用者對記錄說做的修改,增加或刪除記錄都不會反映到記錄集中。支援向前或向後移動

  引數B為記錄集的鎖定型別,其取值為:

  1 鎖定型別,預設的,只讀,不能作任何修改

  2 當編輯時立即鎖定記錄,最安全的方式

  3 只有在呼叫Update方法時才鎖定記錄集,而在此前的其他操作仍可對當前記錄進行更改、插入和刪除等

  4 當編輯時記錄不會被鎖定,而更改、插入和刪除是在批處理方式下完成的

  開啟資料記錄集方法其實不止一種,但是我們用的最多的就是

  rs.open sql,1,1的方法,可是後面的數字引數很多人不解其意,下面我們來介紹一下。

  其實open方法後面有多個引數

  CursorType LockType CommandType

  比如 rs.open sql,1,1

  也可以寫成

  rs.cursorType = 1

  rs.LockType = 1

  rs.open sql

  其中CursorType代表從一個表或者一個SQL查詢結果返回的記錄。

  這個引數有四個值分別是:

  adOpenForwardOnly 表示只允許在記錄集內的記錄間往前移動。這個是預設值。

  adOpenKeyset 反映由其它使用者所做的對記錄的改變或者刪除動作,但並不反映由其它使用者做作的新增新記錄的動作。

  adOpenDynamic 反映由其它使用者所做的對記錄的改變或者刪除動作,包括新增的新記錄

  adOpenStatic 不反映其它使用者對記錄所做的修改,新增,刪除動作。

  這四個值VBSCRIPT預定義位

  adOpenForwardOnly = 0

  adOpenKeyset = 1

  adOpenDynamic = 2

  adOpenStatic = 3

  lockType 表示當開啟記錄集時,資料提供者用於鎖定資料庫的型別:

  adLockReadOnly 資料不能改變,這是預設值!

  adLockPessimistic 資料提供者在開始編輯資料的時候鎖定記錄

  adLockOptimistic 僅當呼叫update方法時,資料提供者鎖定記錄

  adLockBatchOptimistic 用於批處理修改

  他們的常量值定義分別是:

  adLockReadOnly = 1

  adLockPessimistic = 2

  adLockOptimistic = 3

  adLockBatchOptimistic = 4

  rs.open sql,conn,1,1 讀取記錄 select

  rs.open sql,conn,1,3 只更新記錄最好 update

  rs.open sql,conn,2,3 插入和刪除最好 insert delete

下面的解釋:

1. 什么是遊標?

遊標,也有人稱為游標。概括的講,它是基於記錄的。

過去,關係型資料庫沒有象現在這樣被廣泛的應用。那時候,人們大多使用 dBase 這樣的小型資料庫軟體。這類資料庫確切的說應為資料檔案管理軟體。他們是面向記錄的。

不過,這種方式也許更符合人們的習慣。比如,我們在電話本中查詢號碼,在學生檔案中查詢檔案,最終都要歸結於其中的一個號碼,一個檔案,那就是一條記錄。現實生活中,我們在一張表格中尋找某一項時,可能會用手一條一條逐行的掃過,以幫助我們找到所需的那條記錄。對應於資料庫來說,這就是遊標的模型。所以,你可以這樣想象:表格是資料庫中的表,而我們的手好比是遊標。

所以,當你使用類似 .MoveNext,.MoveLast 這樣的語句時,覺得再自然不過了。

現在,你明白什么是遊標了吧。遊標就是資料的 ' 定位系統 ' 。

這個 ' 定位系統 ' 粗分有兩種:伺服器遊標和客戶遊標。對應於 ADO 中的 CursorLocation 。舉例來說:

Set rs = Server.CreateObject("ADODB.RecordSet")
rs.CursorLocation = adUseServer      '預設,使用伺服器遊標
.....
rs.CursorLocation = adUseClient      '使用客戶遊標

2. 什么是伺服器遊標?

或者稱為 API 伺服器遊標。

假設你要查詢有關程式語言的書,寫成 SQL 語句就是:SELECT book_id,book_title FROM books WHERE book_catalog = '程式設計' ORDER BY book_title,同時你指定使用伺服器遊標。

這條語句傳送到伺服器,伺服器對資料進行檢索,將符合查詢條件的記錄集合放入臨時表(對某些遊標型別是這樣)中。每當你進行 .MoveNext 操作,伺服器就會發送一條記錄到客戶端的緩衝區,然後你才可以使用它。

3. 什么是 CacheSize ?

繼續上面的例子,假設符合查詢條件的記錄有100個,也就是說,用 .MoveNext 這種方法遍歷該結果集需要同伺服器互動100次。我們可以通過設定 CacheSize 使客戶與伺服器的通訊變少。上面的例子其實就是 CacheSize=1 的情況,這是預設值。

假設 CacheSize=4,當 RecordSet 物件開啟時,伺服器傳送4條記錄到客戶端。前4次的 .MoveNext 操作實際上是在客戶緩衝區中得到資料,當第5次 .Movenext 時,伺服器才傳送下一個4條記錄。由此,減少了客戶與伺服器間的網路通訊。

那么是不是說 CacheSize 越大越好呢?千萬不要想當然。萬事都有兩面性,CacheSize 也一樣。客戶端請求資料,伺服器傳送資料,這個過程有點象交通管理。CacheSize 過高,會阻塞交通,甚至引起資料丟失(比如當 Cachesize 大於客戶端緩衝區時)。對於不同的應用,所取的值也不同。

另外要指出的是,使用任何形式的遊標都不是最有效的訪問資料的方法,Cachesize 有的時候並不是瓶頸,儘量將使用遊標的程式轉換為面向結果集的程式,效能會提高很多。

3. 什么是客戶遊標?

既然遊標是資料的 ' 定位系統 ',那么在客戶端也可以完成。

客戶遊標的產生由來已久,當初是為了彌補伺服器的不足(有些資料庫引擎就不支援遊標)。隨著伺服器遊標的出現,客戶遊標似乎已經過時了,不過還是那句話:萬事都有兩面性,在 internet 上,與資料庫的連線並不是永久的,使用客戶遊標能使我們獲得同使用伺服器遊標一樣的功能。

當 CursorLoction 屬性設成 adUseClient 時,微軟的遊標服務( Cursor Service )建立 RecordSet 物件,用前向 / 只讀的遊標方式從伺服器將所有查詢結果檢索出來,並且儲存在客戶緩衝區中。當應用程式通過 ADO 請求資料時,遊標服務就從客戶緩衝區中檢取資料。這種方式在連線遠端伺服器時非常有用,它會提高應用程式的效能。如果你訪問的資料庫是 Jet 資料庫( Access ),而且在本地,那麼用客戶遊標非但不提高效能,還會使效能下降。這時候,資料將被快取兩次,資料庫一次,遊標服務一次。

如果考慮應用的功能,客戶遊標功能是很完善的,它能支援某些資料庫不能完成的操作( 視資料庫的情況而定 )。

4. 什么是 DisConnected RecordSet ?

我們使用了客戶遊標,就可以斷開與資料庫的連線,釋放 Connection 物件。這樣的結果集就是 DisConnected RecordSet。舉例說明:

Dim c As New ADODB.Connection
Dim r As New ADODB.Recordset
On Error GoTo handler
   
c.ConnectionString = connectStr
c.CursorLocation = adUseClient
c.Open
Set r.ActiveConnection = c
r.Open SqlText, , adOpenKeyset, adLockBatchOptimistic, -1
Set r.ActiveConnection = Nothing   ' This disconnects the recordset.
c.Close
Set c = Nothing
......
......   
' Recordset is now in disconnected state; do something with it.
r.Close
Set r = Nothing