前言
大家都對SqlServer視圖、存盤程序、觸發器的創建與使用有一定的了解了,我們來看下什么是游標,怎么使用,什么時候用,
SqlServer視圖的創建與使用
SqlServer存盤程序的創建與使用
SqlServer觸發器的創建與使用
什么是游標
1、游標的概念
游標(Cursor)是處理資料的一種方法,為了查看或者處理結果集中的資料,游標提供了在結果集中一次一行或者多行前進或向后瀏覽資料的能力
它使用戶可逐行訪問由SQL Server回傳的結果集,使用游標(cursor)的一個主要的原因就是把集合操作轉換成單個記錄處理方式,
用SQL語言從資料庫中檢索資料后,結果放在記憶體的一塊區域中,且結果往往是一個含有多個記錄的集合,
游標機制允許用戶在SQL server內逐行地訪問這些記錄,按照用戶自己的意愿來顯示和處理這些記錄,
我們可以把游標當作一個指標,它可以指定結果中的任何位置,然后允許用戶對指定位置的資料進行處理,
2、游標的組成
游標包含兩個部分:一個是游標結果集、一個是游標位置,
游標結果集:定義該游標得SELECT陳述句回傳的行的集合,游標位置:指向這個結果集某一行的當前指標,
3、游標的分類
游標共有3類:API服務器游標、Transaction-SQL游標和API客戶端游標,
其中前兩種游標都是運行在服務器上的,所以又叫做服務器游標,
API服務器游標
API服務器游標主要應用在服務上,當客戶端的應用程式呼叫API游標函式時,服務器會對API函式進行處理,使用API函式和方法可以實作如下功能:
(1)打開一個連接,
(2)設定定義游標特征的特性或屬性,API自動將游標映射到每個結果集,
(3)執行一個或多個Transaction-SQL陳述句,
(4)使用API函式或方法提取結果集中的行,
API服務器游標包含以下四種:靜態游標、動態游標、只進游標、鍵集驅動游標(Primary key)
靜態游標的完整結果集將打開游標時建立的結果集存盤在臨時表中,(靜態游標始終是只讀的),靜態游標具有以下特點:總是按照打開游標時的原樣顯示結果集;不反映資料庫中作的任何修改,也不反映對結果集行的列值所作的更改;不顯示打開游標后在資料庫中新插入的行;組成結果集的行被其他用戶更新,新的資料值不會顯示在靜態游標中;但是靜態游標會顯示打開游標以后從資料庫中洗掉的行,
動態游標與靜態游標相反,當滾動游標時動態游標反映結果集中的所有更改,結果集中的行資料值、順序和成員每次提取時都會改變,
只進游標不支持滾動,它只支持游標從頭到尾順序提取資料行,注意:只進游標也反映對結果集所做的所有更改,
鍵集驅動游標同時具有靜態游標和動態游標的特點,當打開游標時,該游標中的成員以及行的順序是固定的,鍵集在游標打開時也會存盤到臨時作業表中,對非鍵集列的資料值的更改在用戶游標滾動的時候可以看見,在游標打開以后對資料庫中插入的行是不可見的,除非關閉重新打開游標,
Transaction-SQL游標
該游標是基于Declare Cursor 語法,主要用于Transaction-SQL腳本、存盤程序以及觸發器中,Transaction-SQL游標在服務器處理由客戶端發送到服務器的Transaction-SQL陳述句,
在存盤程序或觸發器中使用Transaction-SQL游標的程序為:
(1)宣告Transaction-SQL變數包含游標回傳的資料,為每個結果集列宣告一個變數,宣告足夠大的變數來保存列回傳的值,并宣告變數的型別為可從資料型別隱式轉換得到的資料型別,
(2)使用Declare Cursor陳述句將Transaction-SQL游標與Select陳述句相關聯,還可以利用Declare Cursor定義游標的只讀、只進等特性,
(3)使用Open陳述句執行Select陳述句填充游標,
(4)使用Fetch Into陳述句提取單個行,并將每列中得資料移至指定的變數中,注意:其他Transaction-SQL陳述句可以參考那些變數來訪問提取的資料值,Transaction-SQL游標不支持提取行塊,
(5)使用Close陳述句結束游標的使用,注意:關閉游標以后,該游標還是存在,可以使用Open命令打開繼續使用,只有呼叫Deallocate陳述句才會完全釋放,
客戶端游標
該游標將使用默認結果集把整個結果集高速快取在客戶端上,所有的游標操作都在客戶端的高速快取中進行,
注意:客戶端游標只支持只進和靜態游標,不支持其他游標,
怎么使用游標
游標的生命周期包含有五個階段,也是它使用的順序:
- 宣告游標(創建);
- 打開游標;
- 讀取游標資料;
- 關閉游標;
- 釋放游標,
1、宣告游標
宣告游標是為游標指定獲取資料時所使用的Select陳述句,宣告游標并不會檢索任何資料,它只是為游標指明了相應的Select 陳述句,
在SQL Server中創建游標物件使用關鍵之declare(變數宣告)以及curosr(游標),
宣告游標的引數
(1)Local與Global:Local表示游標的作用于僅僅限于其所在的存盤程序、觸發器以及批處理中、執行完畢以后游標自動釋放,Global表示的是該游標作用域是整個會話層,由連接執行的任何存盤程序、批處理等都可以參考該游標名稱,僅在斷開連接時隱性釋放,
(2)Forward_only與Scroll:前者表示為只進游標,后者表示為可以隨意定位,默認為前者,
(3)Static、Keyset與Dynamic: 第一個表示定義一個游標,其資料存放到一個臨時表內,對游標的所有請求都從臨時表中應答,因此,對該游標進行提取操作時回傳的資料不反映對基表所作的修改,并且該游標不允許修改,Keyset表示的是,當游標打開時,鍵集驅動游標中行的身份與順序是固定的,并把其放到臨時表中,Dynamic表示的是滾動游標時,動態游標反映對結果集內所有資料的更改,
(4)Read_only 、Scroll_Locks與Optimistic:第一個表示的是只讀游標,第二個表示的是在使用的游標結果集資料上放置鎖,當行讀取到游標中然后對它們進行修改時,資料庫將鎖定這些行,以保證資料的一致性,Optimistic的含義是游標將資料讀取以后,如果這些資料被更新了,則通過游標定位進行的更新與洗掉操作將不會成功,
標準游標:
declare
MyCursor cursor
for select Name,ClassId from a_Students只讀游標
declare
MyCursor cursor
for SELECT s.Name,sc.ClassName FROM a_Students s
INNER JOIN a_StudentClass sc ON s.ClassId=sc.ClassId
For Read Only可更新游標
declare
MyCursor cursor
for SELECT s.Name,sc.ClassName FROM a_Students s
INNER JOIN a_StudentClass sc ON s.ClassId=sc.ClassId
For UpDate
--宣告(創建)游標物件(標準游標) declare MyCursor cursor for SELECT s.Name,sc.ClassName FROM a_Students s INNER JOIN a_StudentClass sc ON s.ClassId=sc.ClassId;
2、打開游標物件
打開游標使用Open陳述句用于打開Transaction-SQL服務器游標,執行Open陳述句的程序中就是按照Select陳述句進行填充資料,打開游標以后游標位置在第一行,
打開游標
全域游標:Open Global MyCursor 區域游標: Open MyCursor
游標物件創建之后,必須打開之后才能進行使用,使用關鍵字open,
--打開游標 open MyCursor;
3、讀取游標資料
在打開游標以后,使用Fetch陳述句從Transaction-SQL服務器游標中檢索特定的一行,使用Fetch操作,可以使游標移動到下一個記錄,并將游標回傳的每個列得資料分別賦值給宣告的本地變數,
Fetch [Next | Prior | First | Last | Absolute n | Relative n ] From MyCursor
Into @GoodsID,@GoodsName
其中:Next表示回傳結果集中當前行的下一行記錄,如果第一次讀取則回傳第一行,默認的讀取選項為Next
Prior表示回傳結果集中當前行的前一行記錄,如果第一次讀取則沒有行回傳,并且把游標置于第一行之前,
First表示回傳結果集中的第一行,并且將其作為當前行,
Last表示回傳結果集中的最后一行,并且將其作為當前行,
Absolute n 如果n為正數,則回傳從游標頭開始的第n行,并且回傳行變成新的當前行,如果n為負,則回傳從游標末尾開始的第n行,并且回傳行為新的當前行,如果n為0,則回傳當前行,
Relative n 如果n為正數,則回傳從當前行開始的第n行,如果n為負,則回傳從當前行之前的第n行,如果為0,則回傳當前行,
--讀取游標資料 --宣告兩個變數接收從游標中取出的值 declare @Name varchar(50),@ClassName varchar(50); --移動游標取值 fetch next from MyCursor into @Name,@ClassName; print(@Name); print(@ClassName);
4、關閉游標
游標使用完畢之后需要關閉,以及資源的釋放,關鍵字close,deallocate,
--關閉游標 CLOSE MyCursor
5、釋放游標
游標使用完畢之后需要關閉,以及資源的釋放,關鍵字close,deallocate,
--釋放游標 DEALLOCATE MyCursor
6、修改游標資料
--修改當前游標資料 --a_Students表名,Name欄位名,MyCursor游標名 UpDate a_Students Set Name = '孫悟空111' Where CURRENT Of MyCursor;
7、洗掉游標資料
--洗掉當前游標資料 --a_Students表名 Delete From a_Students Where Current Of MyCursor
完整實體
使用游標查詢資料,只獲取取欄位姓名(Name),和欄位班級(ClassName)
--宣告(創建)游標物件(標準游標) declare MyCursor cursor for SELECT s.Name,sc.ClassName FROM a_Students s INNER JOIN a_StudentClass sc ON s.ClassId=sc.ClassId; --宣告兩個變數接收從游標中取出的值 declare @Name varchar(50),@ClassName varchar(50); begin --打開游標 open MyCursor; --移動游標取值 fetch next from MyCursor into @Name,@ClassName; --這里對游標的狀態進行判斷,如果為0,證明游標中有值 while @@FETCH_STATUS = 0 BEGIN print(@Name); print(@ClassName); --讓游標繼續往后移動 fetch next from MyCursor into @Name,@ClassName end --關閉游標 CLOSE MyCursor --釋放游標 DEALLOCATE MyCursor end
什么時候使用游標
當你要處理的結果集比較龐大,而你要對某一行或幾行進行操作的時候,要考慮使用游標,
特別是對結果集中第幾行進行行操作的時候,一般可以考慮使用游標,
但也不是唯一的方法,可以利用別的方法來替代,一般比較復雜的存盤程序里面會出現游標的影子,
- 現存系統有一些游標,我們查詢必須通過游標來實作
- 作為一個備用方式,當我們窮盡了while回圈,子查詢,臨時表,表變數,自建函式或其他方式扔來無法實作某些查詢的時候,使用游標實作.
游標使用的建議
游標用于按順序遍歷結果集,
但一般情況下,應盡量避免使用游標,
原因:
- 游標違背了關系模型,即按集合來考慮問題的思想;
- 游標逐行對紀錄進行操作,會帶來額外的開銷,使用游標的解決方案通常比使用集合的解決方案要慢得多;
- 使用游標的解決方案,需要用很多代碼來描述對游標的操作,因此代碼更長,可讀性更差,也更難以維護,
如果要使用,一定記住要記住:
- 用完之后一定要關閉和釋放,盡量不要在大量資料上定義游標;
- 盡量不要使用游標上更新資料;
- 盡量不要使用insensitive, static和keyset這些引數定義游標;
- 如果可以,盡量使用FAST_FORWARD關鍵字定義游標;
- 如果只對資料進行讀取,當讀取時只用到FETCH NEXT選項,則最好使用FORWARD_ONLY引數,
我們就介紹到這里吧,各位拜了個拜,
歡迎關注訂閱微信公眾號【熊澤有話說】,更多好玩易學知識等你來取作者:熊澤-學習中的苦與樂 公眾號:熊澤有話說 出處: https://www.cnblogs.com/xiongze520/p/14633171.html 創作不易,任何人或團體、機構全部轉載或者部分轉載、摘錄,請在文章明顯位置注明作者和原文鏈接,
|
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/274017.html
標籤:其他
