SQL SERVER CURSOR
游標(Cursor)它使用戶可逐行訪問由SQL Server返回的結果集。
使用游標(cursor)的一個主要的原因就是把集合操作轉換成單個記錄處理方式。
用SQL語言從數據庫中檢索數據后,結果放在內存的一塊區域中,且結果往往是一個含有多個記錄的集合。
游標機制允許用戶在SQL server內逐行地訪問這些記錄,按照用戶自己的意愿來顯示和處理這些記錄。
二:游標的基本形式 聲明游標:形式1 DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR FOR select_statement [FOR {READ ONLY | UPDATE ][OF column_list]}] 形式2 DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC] [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] FOR select_statement [FOR {READ ONLY | UPDATE ][OF column_list]}] INSENSITIVE關鍵字指明要為檢索到的結果集建立一個臨時拷貝,以后的數據從這個臨時拷貝中獲取。 如果在后來游標處理的過程中,原有基表中數據發生了改變,那么它們對于該游標而言是不可見的。這種不敏感的游標不允許數據更改。 SCROLL關鍵字指明游標可以在任意方向上滾動。所有的fetch選項(first、last、next、relative、absolute)都可以在游標中使用。 如果忽略該選項,則游標只能向前滾動(next)。 Select_statement指明SQL語句建立的結果集。Transact SQL語句COMPUTE、COMPUTE BY、FOR BROWSE和INTO在游標聲明的選擇語句中不允許使用。 READ ONLY指明在游標結果集中不允許進行數據修改。 UPDATE關鍵字指明游標的結果集可以修改。 OF column_list指明結果集中可以進行修改的列。缺省情況下(使用UPDATE關鍵字),所有的列都可進行修改。 LOCAL關鍵字指明游標是局部的,它只能在它所聲明的過程中使用。 GLOBAL關鍵字使得游標對于整個連接全局可見。全局的游標在連接激活的任何時候都是可用的。只有當連接結束時,游標才不再可用。 FORWARD_ONLY指明游標只能向前滾動。 STATIC的游標與INSENSITIVE的游標是相同的。 KEYSET指明選取的行的順序。SQL Server將從結果集中創建一個臨時關鍵字集。如果對數據庫的非關鍵字列進行了修改,則它們對游標是可見的。 因為是固定的關鍵字集合,所以對關鍵字列進行修改或新插入列是不可見的。 DYNAMIC指明游標將反映所有對結果集的修改。 SCROLL_LOCK是為了保證游標操作的成功,而對修改或刪除加鎖。 OPTIMISTIC指明哪些通過游標進行的修改或者刪除將不會成功。 注意: · 如果在SELECT語句中使用了DISTINCT、UNION、GROUP BY語句,且在選擇中包含了聚合表達式,則游標自動為INSENSITIVE的游標。 · 如果基表沒有唯一的索引,則游標創建成INSENSITIVE的游標。 · 如果SELECT語句包含了ORDER BY,而被ORDER BY的列并非唯一的行標識,則DYNAMIC游標將轉換成KEYSET游標。 如果KEYSET游標不能打開,則將轉換成INSENSITIVE游標。使用SQL ANSI-92語法定義的游標同樣如此,只是沒有INSENSITIVE關鍵字而已。 打開游標 打開游標就是創建結果集。游標通過DECLARE語句定義,但其實際的執行是通過OPEN語句。語法如下: OPEN { { [GLOBAL] cursor_name } | cursor_variable_name} GLOBAL指明一個全局游標。 Cursor_name是被打開的游標的名稱。 Cursor_variable_name是所引用游標的變量名。該變量應該為游標類型。 在游標被打開之后,系統變量@@cursor_rows可以用來檢測結果集的行數。 @@cursor_rows為負數時,表示游標正在被異步遷移,其絕對值(如果@@cursor_rows為-5,則絕對值為5)為當前結果集的行數。 異步游標使用戶在游標被完全遷移時仍然能夠訪問游標的結果。 從游標中取值 在從游標中取值的過程中,可以在結果集中的每一行上來回移動和處理。 如果游標定義成了可滾動的(在聲明時使用SCROLL關鍵字),則任何時候都可取出結果集中的任意行。 對于非滾動的游標,只能對當前行的下一行實施取操作。結果集可以取到局部變量中。Fetch命令的語法如下: FETCH [NEXT | PRIOR| FIRST | LAST | ABSOLUTE {n | @nvar} | RELATIVE {n | @nvar}] FROM [GLOBAL] cursor_name} | cursor_variable_name} [INTO @variable_name ][,……n]] NEXT指明從當前行的下一行取值。 PRIOR指明從當前行的前一行取值。 FIRST是結果集的第一行。 LAST是結果集的最后一行。 ABSOLUTE n表示結果集中的第n行,該行數同樣可以通過一個局部變量傳播。行號從0開始,所以n為0時不能得到任何行。 RELATIVE n表示要取出的行在當前行的前n行或后n行的位置上。如果該值為正數,則要取出的行在當前行前n行的位置上,如果該值為負數,則返回當前行的后n行。 INTO @cursor_variable_name表示游標列值存儲的地方的變量列表。 該列表中的變量數應該與DECLARE語句中選擇語句所使用的變量數相同。 變量的數據類型也應該與被選擇列的數據類型相同。直到下一次使用FETCH語句之前,變量中的值都會一直保持。 每一次FETCH的執行都存儲在系統變量@@fetch_status中。 如果FETCH成功,則@@fetch_status被設置成0。@@fetch_status為-1表示已經到達了結果集的一部分(例如,在游標被打開之后,基表中的行被刪除)。 @@fetch_status可以用來構造游標處理的循環。 關閉游標 CLOSE語句用來關閉游標并釋放結果集。游標關閉之后,不能再執行FETCH操作。如果還需要使用FETCH語句,則要重新打開游標。語法如下: CLOSE [GLOBAL] cursor_name | cursor_variable_name 釋放游標 游標使用不再需要之后,要釋放游標。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 FORSELECT 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). 對于大結果集要考慮使用異步游標,盡可能地把控制權交給調用者。當返回相當大的結果集到可移動的表格時,異步游標特別有用.原文出處:http://www.cnblogs.com/virtual/articles/1726952.html
轉載于:https://www.cnblogs.com/junkai/archive/2013/02/28/2936849.html
總結
以上是生活随笔為你收集整理的SQL SERVER CURSOR的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Hibenate工具类(实现增/删/改/
- 下一篇: 保存GNOME桌面环境中声卡的音量设置