數據庫游標及其優點


游標(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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM