T-SQL 之 遊標

遊標的原理 
    一般情況下,SQL查詢結果都是多條紀錄的結果集,而高級語言一次只能處理一條紀錄,用遊標機制,將多條紀錄一次一條讀取出來處理。
從而把對集合的操作轉化爲對單個紀錄的處理。遊標使用的步驟如下:

1、說明遊標。說明遊標的時候並不執行select語句。
 declare <遊標名> cursor for <select語句>;
 
2、打開遊標。打開遊標實際上是執行相應的select語句,把查詢結果讀取到緩衝區中。這時候遊標處於活動狀態,指針指向查詢結果集的第一條紀錄。
 open <遊標名>;
 
3、推進遊標指針並讀取當前紀錄。用fetch語句把遊標指針向前推進一條紀錄,同時將緩衝區中的當前紀錄讀取出來送到變量中。
fetch語句通常用在一個循環結構體中,通過循環執行fetch語句逐條取出結果集中的行進行處理。現在好多數據庫中,還允許任意方向任意步長易懂遊標指針,
而不僅僅是把遊標指針向前推進一行了。
 fetch <遊標名> into <變量1>,<變量2>...
 
4、關閉遊標。用close語句關閉遊標,釋放結果集佔用的緩衝區及其他資源。遊標關閉後,就不再和原來的查詢結果集相聯繫。但遊標可以再次打開,
與新的查詢結果相聯繫。
 close <遊標名>;

 5、釋放遊標
遊標使用不再需要之後,要釋放遊標。DEALLOCATE語句釋放數據結構和遊標所加的鎖。
語法如下:DEALLOCATE [GLOBAL] cursor_name | cursor_variable_name
遊標的基本使用模板
declare 
        declare  遊標名[scroll]  cursor  for select語句[for update [of列表名]]

        定義一個遊標,使之對應一個select語句

       for update任選項,表示該遊標可用於對當前行的修改與刪除

open

       打開一個遊標,執行遊標對應的查詢,結果集合爲該遊標的活動集

       open  遊標名

fetch

       在活動集中將遊標移到特定的行,並取出該行數據放到相應的變量中

       fetch [next | prior | first | last | current | relative n | absolute m] 遊標名into  [變量表]

close

       關閉遊標,釋放活動集及其所佔資源。需要再使用該遊標時,執行open語句

       close  遊標名

deallocate

       刪除遊標,以後不能再對該遊標執行open語句

       deallocate 遊標名

 

@@FETCH_STATUS返回被FETCH 語句執行的最後遊標的狀態.

       0 fetch語句成功        -1 fetch語句失敗        -2 被提取的行不存在

複製代碼
DECLARE Employee_Cursor CURSOR FOR SELECT EmployeeID, Title FROM AdventureWorks.HumanResources.Employee OPEN Employee_Cursor FETCH NEXT FROM Employee_Cursor WHILE @@FETCH_STATUS = 0 BEGIN --//TO DO...   FETCH NEXT FROM Employee_Cursor END CLOSE Employee_Cursor DEALLOCATE Employee_Cursor GO
複製代碼

遊標性能問題
最好的改進遊標性能的技術就是:能避免時就避免使用遊標,儘可能用對應的語句完成相同的功能(一般情況下,考慮得當效率能大大提升)。

SQL Server是關係數據庫,其處理數據集比處理單行好得多,單獨行的訪問根本不適合關係DBMS。若有時無法避免使用遊標,
則可以用如下技巧來優化遊標的性能。

(1). 除非必要否則不要使用static/insensitive遊標。打開static遊標會造成所有的行都被拷貝到臨時表。這正是爲什麼它對變化不敏感的原因
——它實際上是指向臨時數據庫表中的一個備份。
很自然,結果集越大,聲明其上的static遊標就會引起越多的臨時數據庫的資源爭奪問題。

(2). 除非必要否則不要使用keyset遊標。和static遊標一樣,打開keyset遊標會創建臨時表。雖然這個表只包括基本表的一個關鍵字列(除非不存在唯一關鍵字),
但是當處理大結果集時還是會相當大的。

(3). 當處理單向的只讀結果集時,使用fast_forward代替forward_only。使用fast_forward定義一個forward_only,則read_only遊標具有一定的內部性能優化。
(4). 使用read_only關鍵字定義只讀遊標。這樣可以防止意外的修改,並且讓服務器瞭解遊標移動時不會修改行。
(5). 小心事務處理中通過遊標進行的大量行修改。根據事務隔離級別,這些行在事務完成或回滾前會保持鎖定,這可能造成服務器上的資源爭奪。
(6). 小心動態光標的修改,尤其是建在非唯一聚集索引鍵的表上的遊標,因爲他們會造成“Halloween”問題——對同一行或同一行的重複的錯誤的修改。
因爲SQL Server在內部會把某行的關鍵字修改成一個已經存在的值,並強迫服務器追加下標,使它以後可以再結果集中移動。當從結果集的剩餘項中存取時,
又會遇到那一行,然後程序會重複,結果造成死循環。
(7). 對於大結果集要考慮使用異步遊標,儘可能地把控制權交給調用者。當返回相當大的結果集到可移動


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章