1. 程式人生 > >SQLserver遊標原理和使用方法

SQLserver遊標原理和使用方法

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

1.1 遊標和遊標的優點

    在資料庫中,遊標是一個十分重要的概念。遊標提供了一種對從表中檢索出的資料進行操作的靈活手段,就本質而言,遊標實際上是一種能從包括多條資料記錄的結果集中每次提取一條記錄的機制。遊標總是與一條T_SQL 選擇語句相關聯因為遊標由結果集(可以是零條、一條或由相關的選擇語句檢索出的多條記錄)和結果集中指向特定記錄的遊標位置組成。

當決定對結果集進行處理時,必須宣告一個指向該結果集的遊標。如果曾經用 C 語言寫過對檔案進行處理的程式,那麼遊標就像您開啟檔案所得到的檔案控制代碼一樣,只要檔案開啟成功,該檔案控制代碼就可代表該檔案。對於遊標而言,其道理是相同的。可見遊標能夠實現按與傳統程式讀取平面檔案類似的方式處理來自基礎表的結果集,從而把表中資料以平面檔案的形式呈現給程式。

    我們知道關係資料庫管理系統實質是面向集合的,在MS SQL SERVER 中並沒有一種描述表中單一記錄的表達形式,除非使用where 子句來限制只有一條記錄被選中。因此我們必須藉助於遊標來進行面向單條記錄的資料處理。

    由此可見,遊標允許應用程式對查詢語句select 返回的行結果集中每一行進行相同或不同的操作,而不是一次對整個結果集進行同一種操作;它還提供對基於遊標位置而對錶中資料進行刪除或更新的能力;而且,正是遊標把作為面向集合的資料庫管理系統和麵向行的程式設計兩者聯絡起來,使兩個資料處理方式能夠進行溝通。

1.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 遊標使用在伺服器端,所以被稱為伺服器遊標,也被稱為後臺遊標,而客戶端遊標被稱為前臺遊標。在本章中我們主要講述伺服器(後臺)遊標。

select count(id) from info

select * from info

--清除所有記錄

truncate table info

declare @i int

set @i=1

while @i<1000000

begin

 insert into info values('Justin'+str(@i),'深圳'+str(@i))

 set @[email protected]+1

end

1.3 遊標操作

使用遊標有四種基本的步驟:宣告遊標開啟遊標提取資料關閉遊標

宣告遊標

象使用其它型別的變數一樣,使用一個遊標之前,首先應當宣告它。遊標的宣告包括兩個部分:遊標的名稱;這個遊標所用到的SQL語句。如要宣告一個叫作Cus-tomerCursor的遊標用以查詢地址在北京的客戶的姓名、帳號及其餘額,您可以編寫如下程式碼:

DECLARE CustomerCursor CURSOR FOR

SELECT acct_no,name,balance

FROM customer

WHERE province="北京";

在遊標的宣告中有一點值得注意的是,如同其它變數的宣告一樣,宣告遊標的這一段程式碼行是不執行的,您不能將debug時的斷點設在這一程式碼行上,也不能用IF...END IF語句來宣告兩個同名的遊標,如下列的程式碼就是錯誤的。

IF Is_prov="北京"THEN

DECLARE CustomerCursor CURSOR FOR

SELECT acct_no,name,balance

FROM customer

WHERE province="北京";

ELSE

DECLARE CustomerCursor CURSOR FOR

SELECT acct_no,name,balance

FROM customer

WHERE province〈〉"北京";

END IF

開啟遊標

聲明瞭遊標後在作其它操作之前,必須開啟它。開啟遊標是執行與其相關的一段SQL語句,例如開啟上例宣告的一個遊標,我們只需鍵入:

OPEN CustomerCursor;

由於開啟遊標是對資料庫進行一些SQL SELECT的操作,它將耗費一段時間,主要取決於您使用的系統性能和這條語句的複雜程度。如果執行的時間較長,可以考慮將螢幕上顯示的滑鼠改為hourglass。

提取資料

當用OPEN語句打開了遊標並在資料庫中執行了查詢後,您不能立即利用在查詢結果集中的資料。您必須用FETCH語句來取得資料一條FETCH語句一次可以將一條記錄放入程式設計師指定的變數中事實上,FETCH語句是遊標使用的核心。在DataWindow和DataStore中,執行了Retrieve()函式以後,查詢的所有結果全部可以得到;而使用遊標,我們只能逐條記錄地得到查詢結果。

已經宣告並開啟一個遊標後,我們就可以將資料放入任意的變數中。在FETCH語句中您可以指定遊標的名稱和目標變數的名稱。如下例:

FETCH CustmerCur-sor

INTO:ls_acct_no,

:ls_name,

:ll_balance;

從語法上講,上面所述的就是一條合法的取資料的語句,但是一般我們使用遊標卻還應當包括其它的部分。正如我們前面所談到的,遊標只能一次從後臺資料庫中取一條記錄,而在多數情況下,我們所想要作的是在資料庫中從第一條記錄開始提取,一直到結束。所以我們一般要將遊標提取資料的語句放在一個迴圈體內,直至將結果集中的全部資料提取後,跳出迴圈圈通過檢測SQLCA.SQL-CODE的值,可以得知最後一條FETCH語句是否成功。一般,當SQLCODE值為0時表明一切正常,100表示已經取到了結果集的末尾,而其它值均表明操作出了問,這樣我們可以編寫以下的程式碼:

lb_continue=True

ll_total=0

DO WHILE lb_continue

FETCH CustomerCur-sor

INTO:ls_acct_no,

:ls_name,

:ll_balance;

If sqlca.sqlcode=0 Then

ll_total+=ll_balance

Else

lb_continue=False

End If

LOOP

迴圈體的結構有多種,這裡提到的是最常見的一種。也有的程式設計師喜愛將一條FETCH語句放在迴圈體的前面,迴圈體內再放置另外一條FETCH語句,並檢測SQLCA.SQLCODE是否為100(見以下例項)。但是這樣做,維護時需同時修改兩條FETCH語句,稍麻煩了些。

關閉遊標

在遊標操作的最後請不要忘記關閉遊標,這是一個好的程式設計習慣,以使系統釋放遊標佔用的資源。關閉遊標的語句很簡單:

CLOSE CustomerCursor;

使用Where子句

我們可以動態地定義遊標中的Where子句的引數,例如在本例中我們是直接定義了查詢省份是北京的記錄,但也許在應用中我們要使用一個下拉式列表框,由使用者來選擇要查詢的省份,我們該怎樣做呢?

我們在前面曾經提到過,DECLARE語句的作用只是定義一個遊標,在OPEN語句中這個遊標才會真正地被執行。瞭解了這些,我們就可以很方便地實現這樣的功能,在DECLARE的Where子句中加入變數作引數,如下所示:

DECLARE CustomerCursor CURSOR FOR

SELCECT acct_no,name,balance

FROM customer

WHERE province=:ls_province;

// 定義ls_province的值

OPEN CustomerCursor;

遊標的型別

同其它變數一樣,我們也可以定義遊標的訪問型別:全域性、共享、例項或區域性,遊標變數的命名規範建議也同其它變數一樣。

--宣告遊標

declare my_cursor cursor keyset for select * from info

--刪除遊標資源

deallocate my_cursor

--開啟遊標,在遊標關閉或刪除前都有效

open my_cursor

--關閉遊標

close my_cursor

--宣告區域性變數

declare @id int,@name varchar(20),@address varchar(20)

--定位到指定位置的記錄

fetch absolute 56488 from my_cursor into @id,@name,@address

select @id as id,@name as name,@address as address

--定位到當前記錄相對位置記錄

fetch relative -88 from my_cursor into @id,@name,@address

select @id as id,@name as name,@address as address

--定位到當前記錄前一條

fetch prior from my_cursor into @id,@name,@address

select @id as id,@name as name,@address as address

--定位到當前記錄後一條

fetch next from my_cursor into @id,@name,@address

select @id as id,@name as name,@address as address

--定位到首記錄

fetch first from my_cursor into @id,@name,@address

select @id as id,@name as name,@address as address

--定位到尾記錄

fetch last from my_cursor into @id,@name,@address

select @id as id,@name as name,@address as address

例項

 use database1

declare my_cursor cursor scroll dynamic

 /**//*scroll表示可隨意移動遊標指標(否則只能向前)dynamic表示可以讀寫遊標(否則遊標只讀)*/

for

select productname from  product

open my_cursor

declare @pname sysname

fetch next from my_cursor into @pname

while(@@fetch_status=0)

  begin

    print 'Product Name: ' + @pname

    fetch next from my_cursor into @pname

  end

fetch first from my_cursor into @pname

print @pname

/**//*update product set productname='zzg' where current of my_cursor */

/**//*delete from product where current of my_cursor */

close my_cursor

deallocate my_cursor

1.4 遊標的高階技巧

儘管目前基於SQL語句的後臺資料庫所支援的語言都大致相當,但對遊標的支援卻有著一些差異,例如對滾動遊標支援。所謂滾動遊標,就是程式設計師可以指定遊標向前後任意一個方向滾動。如在Informix中,您甚至還可以將遊標滾向結果集開頭或末尾,使用的語句分別是FETCH FIRST,FETCH LAST、FETCH PRIOR和FETCH NEXT。當程式設計師用FETCH語句,其預設是指FETCH NEXT。由於滾動是在資料庫後臺實現的,所以滾動遊標為使用者程式設計提供了極大的方便。

對遊標支援的另一個不同是可修改遊標。上述遊標的使用都是指只讀遊標,而象Oracle、Sybase等資料庫卻另外支援可作修改的遊標。使用這樣的資料庫,您可以修改或刪除當前遊標所在的行。例如修改當前遊標所在行的使用者的餘額,我們可以如下操作:

UPDATE customer

SET balance=1000

WHERE CURRENT OF customerCursor;

刪除當前行的操作如下:

DELETE FROM Customer

WHERE CURRENT OF CustomerCursor;

但是如果您當前使用的資料庫是Sybase,您需要修改資料庫的引數,將遊標可修改的值定為1,才能執行上述操作。這一賦值在連線資料庫的前後進行均可。

SQLCA.DBParm="Cursor Update=1"

相關推薦

SQLserver遊標原理使用方法

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

SQL遊標原理使用方法

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

清除浮動的原理方法

over back 存在 color float oat hid block play 問題的由來: 在CSS規範中,浮動定位是脫離元素正常流的。所以,只要含有浮動元素的父容器,在顯示時不考慮子元素的位置,就當它們不存在一樣。這就造成了顯示出來,父容器好像空容器一樣。

ArrayList原理、OA信用盤平臺出租LinkedList原理方法叠代器註意事項

move java link ret offer bject 隊列 先進先出 錯誤 叠代器在變量元素OA信用盤平臺出租QQ2952777280【話仙源碼論壇】hxforum.com【木瓜源碼論壇】papayabbs.com的時候要註意事項:    在叠代器叠代元素 的過程中

零基礎大資料學習的10大思維原理方法全部都在這

1、資料核心原理 從“流程”核心轉變為“資料”核心   大資料時代,計算模式也發生了轉變,從“流程”核心轉變為“資料”核心。Hadoop體系的分散式計算框架已經是“資料”為核心的正規化。非結構化資料及分析需求,將改變IT系統的升級方式:從簡單增量到架構變化。大資料下的新思維——計算模式的轉變。   網際

零基礎大數據學習的10大思維原理方法全部都在這

因果關系 喬布斯 準則 努力 半監督學習 經濟 好奇心 人類 大量 1、數據核心原理 從“流程”核心轉變為“數據”核心   大數據時代,計算模式也發生了轉變,從“流程”核心轉變為“數據”核心。Hadoop體系的分布式計算框架已經是“數據”為核心的範式。非結構化數據及分析需求

(good)相位噪聲基礎及測試原理方法

摘要:相位噪聲指標對於當前的射頻微波系統、移動通訊系統、雷達系統等電子系統影響非常明顯,將直接影響系統指標的優劣。該項指標對於系統的研發、設計均具有指導意義。相位噪聲指標的測試手段很多,如何能夠精準的測量該指標是射頻微波領域的一項重要任務。隨著當前接收機相位噪聲指標越來越高,相應的測試技術和測試手段

【資料庫】SQLServer遊標概念作用

遊標實際上是一種能從包括多條資料記錄的結果集中每次提取一條記錄的機制。遊標充當指標的作用。儘管遊標能遍歷結果中的所有行,但他一次只指向一行。 概括來講,SQL的遊標是一種臨時的資料庫物件,既可以用來存放資料庫表中的資料行副本,也可以指向儲存在資料庫中的資料行的指

Python搜尋引擎實現原理方法

如何在龐大的資料中高效的檢索自己需要的東西?本篇內容介紹了Python做出一個大資料搜尋引擎的原理和方法,以及中間進行資料分析的原理也給大家做了詳細介紹。 布隆過濾器 (Bloom Filter) 第一步我們先要實現一個布隆過濾器。 布隆過濾器是大資料領域的一個常見演算法,它的目的是過濾

【APP自動化測試】Monkey的測試原理方法

參考資料:http://blog.csdn.net/io_field/article/details/52189972 一、Monkey測試原理:Monkey是Android中的一個命令列工具,可以執行在模擬器裡或實際裝置中。它向系統傳送偽隨機的使用者事件流(如按鍵輸入、觸控式螢幕輸入、手勢輸入等),實現對

C語言和java中生成隨機數的原理方法

C語言 一.函式 1:int rand(void) 該函式會產生一個[0,RAND_MAX]的偽隨機數,那什麼是偽隨機數? 相當於一個序列a1-an,第一次使用會返回a1, 第二次使用會返回a2….第n次返回an,這樣每次呼叫rand()都能產生一個不同

嵌入式系統交叉除錯原理方法

)的韌體區,對使用使用者不可見;而音樂檔案、電子書等則是存在於外存的使用者區,對使用使用者可見。從中可看成,各個應用程式是分時複用寶貴的記憶體資源。由於成本敏感,記憶體資源的大小是經過精心設計的。對於單個應用程式,也會將程式碼分為常駐記憶體型別和可切換型別。例如,對效能影響比較大的解碼部分程式碼就需要常駐記憶

c++結構體記憶體對齊原理方法

假設我們同時宣告兩個變數:  char a;  short b;  用&(取地址符號)觀察變數a,  b的地址的話,我們會發現(以16位CPU為例):  如果a的地址是0x0000,那麼b的地址將會是0x0002或者是0x0004。  那麼就出現這樣一個問題:0x0001這個地址沒有被使用,那它幹

C# winform Settings 工作原理方法說明

之前的文章說到Winform中Settings的作用,和使用方法,本文補充一些說明 Settings裡的屬性根據範圍分為兩種 “使用者”和“應用程式” 範圍為“應用程式”的屬性,讀取都是從APP.CONFIG裡獲取,設定也可以通過手工修改App.config改變,但是在程式中

正確評估SQL資料庫效能,你必須知道的原理方法

作者簡介: Max Shen(阿特),為了成為資料專家而努力,萬一實現了呢! 昨天寫了一篇如何監視資料庫效能,瞭解資料庫的執行狀態。被有人質疑,說沒有用。說要直接用資料庫的profile和monitor就可以了,到這一步那已經是到了資料庫查詢效能,已經

偽類:after清除浮動的原理方法

浮動元素容器的clearing問題1. 問題的由來有這樣一種情形:在一個容器(container)中,有兩個浮動的子元素。<div>        <div style="float:left;width:45%;"></div>   

Ognl表達式基本原理使用方法

ognl表達式 作用 設置 submit implement ring 獲取request 編碼 組成 1.Ognl表達式語言 1.1.概述 OGNL表達式 OGNL是Object Graphic Navigation Language(對象圖導航語言)的縮寫,他是一個開

viewport原理使用設置移動端自適應的方法

minimum 禁止 有一個 寬度 maximum client 高度 文字 區域 viewport原理和使用和設置移動端自適應的方法 HTML中: <meta name="viewport" content="width=device-width, initial

GPRS DTU工作原理功能 DTU配置方法詳解

端口號 一個 存儲器 端口 modem 出廠 永久 兩種 斷開 GPRS DTU 簡稱GPRS模塊,即串口服務器的無線版,其功能與串口服務器類似。利用移動和聯通遍布全國的GSM網絡,通過短信方式進行數據傳輸。那麽GPRS DTU有什麽功能呢?GPRS DTU怎麽配置?   

STL原始碼剖析——stack的實現原理使用方法詳解

Stack 簡介     stack 是堆疊容器,是一種“先進後出”的容器。     stack 是簡單地裝飾 deque 容器而成為另外一種容器。     使用 stack 時需要加上標頭檔案 #include<s