游標(biāo)可以理解為SQL Server的一種數(shù)據(jù)訪問機(jī)制,它允許用戶訪問數(shù)據(jù)的維度是數(shù)據(jù)行,。用戶可以對每一行數(shù)據(jù)進(jìn)行單獨(dú)處理,,從而降低系統(tǒng)開銷和潛在的阻隔情況,游標(biāo)主要用于存儲過程,,觸發(fā)器和 T_SQL復(fù)雜的腳本中,,它能使查詢結(jié)果集的數(shù)據(jù)用于其它T_SQL語句。在查看或處理結(jié)果集中向前或向后瀏覽每一行數(shù)據(jù)的功能,。與C語言中的指針功能有些相似,,它可以指向結(jié)果集中的任意位置,如果要對結(jié)果集進(jìn)行逐行單獨(dú)處理時(shí),,必須聲明一個指向該結(jié)果集中的游標(biāo)變量,。SQL Server 中的數(shù)據(jù)操作結(jié)果都是面向集合的,并沒有一種描述表中單一記錄的表達(dá)形式,,除非使用WHERE子句限定查詢結(jié)果,,使用游標(biāo)可以補(bǔ)充這種功能,,并且游標(biāo)的使用和操作過程更加靈活。游標(biāo)的生命周期:聲明游標(biāo)→打開游標(biāo)→讀取數(shù)據(jù)→關(guān)閉游標(biāo)→釋放游標(biāo),。DECLARE cursor_name CURSOR [ LOCAL | GLOBAL][ FORWARD_ONLY | SCROLL ][ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ][ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ][ FOR UPDATE [ OF column_name [,...n] ] ]cursor_name:是所定義的游標(biāo)的名稱。LOCAL:對于在其中創(chuàng)建批處理,、存儲過程或觸發(fā)器來說,,該游標(biāo)的作用域是局部的。GLOBAL:指定該游標(biāo)的作用域是全局的FORWARD_ONLY:指定游標(biāo)只能從第一行滾動到最后一行,。FETCH NEXT是唯一支持的數(shù)據(jù)讀取選項(xiàng),,如果在指定FORWARD_ONLY時(shí)不指定STATIC,KEYSET和DYNAMIC關(guān)鍵字,,則游標(biāo)作為DYNAMIC游標(biāo)進(jìn)行操作,,如果FORWARD_ONLY和SCROLL均為指定,則除非指定STATIC,,KEYSET和DYNAMIC關(guān)鍵字,否則默認(rèn)為FORWARD_ONLY,。STATIC,,KEYSET和DYNAMIC游標(biāo)默認(rèn)為SCROLL。與ODBC和ADO這類數(shù)據(jù)庫API不同,,STATIC,,KEYSET和DYNAMIC T_SQL游標(biāo)支持FORWARD_ONLY。STATIC:定義一個游標(biāo),,以創(chuàng)建將該游標(biāo)使用的數(shù)據(jù)臨時(shí)復(fù)本,,對游標(biāo)的所有請求都從tempdb中的臨時(shí)表中不得到應(yīng)答;因此,,在對該游標(biāo)進(jìn)行提取操作時(shí)返回的數(shù)據(jù)中不反映對基表所做的修改,,并且該游標(biāo)不允許修改。KEYSET:指定當(dāng)游標(biāo)打開時(shí),,游標(biāo)重復(fù)的行的成員身份和順序已經(jīng)固定,。對行進(jìn)行唯一標(biāo)識的鍵值內(nèi)置在tempdb內(nèi)一個稱為keyset的表中。DYNAMIC:定義一個游標(biāo),,以反映在滾動游標(biāo)時(shí)對結(jié)果集內(nèi)的各行所做的所有數(shù)據(jù)更改,。行的數(shù)據(jù)值、順序和成員身份在每次提取時(shí)都會更改,,動態(tài)游標(biāo)不支持ABSOLUTE提取選項(xiàng),。FAST_FORWARD:指定啟動了性能優(yōu)化的FORWARD_ONLY、READ_ONLY游標(biāo),。如果指定了SCROLL或FOR_UPDATE,則不能指定FAST_FORWARD,。SCROLL_LOCKS:指定通過游標(biāo)進(jìn)行的定位更新或刪除一定會成功,。將行讀入游標(biāo)時(shí)SQL Server將鎖定這些行,以確保隨后可對它們進(jìn)行修改,,如果還指定了FAST_FORWARD或STATIC,,則不能指定SCROLL_LOCKS。OPTIMISTIC:指定如果行自讀入游標(biāo)以來已得到更新,,則通過游標(biāo)進(jìn)行的定位更新或定位刪除不成功,。當(dāng)將行讀入游標(biāo)時(shí),SQL Server不鎖定行,,它改用timestamp列值比較結(jié)果來確定行讀入游標(biāo)后是否發(fā)生了修改,,如果表不包含timestamp列,它改用校驗(yàn)和值進(jìn)行確定,,如果以修改該行,,則嘗試進(jìn)行的定位更新或刪除將失敗,如果還指定了FAST_FORWARD,,則不能指定OPTIMISTIC,。TYPE_WARNING:指定游標(biāo)從所請求的類型隱式轉(zhuǎn)換為另一種類型時(shí),向客戶端發(fā)送警告消息,。select_statement:是定義游標(biāo)結(jié)果集中的標(biāo)準(zhǔn)SELECT語句,。注:DECLARE <游標(biāo)名>CURSOR FOR 查詢語句; -- 最簡單的游標(biāo)聲明注意:關(guān)閉游標(biāo),需要執(zhí)行下面兩條命令CLOSE 游標(biāo)名稱; --關(guān)閉游標(biāo)DEALLOCATE 游標(biāo)名稱;--撤銷游標(biāo)(釋放資源 )2,、對當(dāng)前位置的數(shù)據(jù)進(jìn)行讀寫,。3、可以對結(jié)果集中的數(shù)據(jù)單獨(dú)操作,,而不是整行執(zhí)行相同的操作,。4、游標(biāo)是面向數(shù)據(jù)集合和面向數(shù)據(jù)行的程序設(shè)計(jì)之間的橋梁,。DECLARE @Id NVARCHAR(MAX) DECLARE @UserName NVARCHAR(MAX) DECLARE @Password NVARCHAR(MAX) DECLARE @NickName NVARCHAR(MAX) create table #tmp (Id NVARCHAR(MAX),UserName NVARCHAR(MAX),Password NVARCHAR(MAX),NickName NVARCHAR(MAX)) --建立臨時(shí)數(shù)據(jù)表
--聲明一個游標(biāo)mycursor,select語句中參數(shù)的個數(shù)必須要和從游標(biāo)取出的變量名相同 DECLARE mycursor CURSOR FOR SELECT Id,UserName,Password,NickName FROM dbo.Users OPEN mycursor --打開游標(biāo) --從游標(biāo)里取出數(shù)據(jù)賦值到我們剛才聲明的變量中(移動游標(biāo)指向到第一條數(shù)據(jù),,提取第一條數(shù)據(jù)存放在變量中) FETCH NEXT FROM mycursor INTO @Id, @UserName,@Password,@NickName --判斷游標(biāo)的狀態(tài) -- 0 fetch語句成功 ---1 fetch語句失敗或此行不在結(jié)果集中 --- 2 被提取的行不存在 WHILE (@@fetch_status = 0) --如果上一次操作成功則繼續(xù)循環(huán) BEGIN --顯示出我們每次用游標(biāo)取出的值 --print (@Id+'--------'+@UserName+'--------'+@Password+'----'+@NickName) --條件判斷 if (@Id>=10) begin INSERT INTO #tmp(Id,UserName,Password,NickName) VALUES(@Id,@UserName,@Password,@NickName) end --用游標(biāo)去取下一條記錄(繼續(xù)取下一行數(shù)據(jù)) FETCH NEXT FROM mycursor INTO @Id,@UserName,@Password,@NickName END CLOSE mycursor --關(guān)閉游標(biāo) DEALLOCATE mycursor --撤銷游標(biāo)(釋放資源 ) SELECT * FROM #tmp; --查詢臨時(shí)表 DROP TABLE #tmp --刪除臨時(shí)表 五,、總結(jié)
建議盡量避免使用游標(biāo),游標(biāo)使用時(shí)會對數(shù)據(jù)行加鎖,,可能會影響其他業(yè)務(wù)的正常操作,。當(dāng)數(shù)據(jù)量大時(shí)執(zhí)行效率也較低。另外,,系統(tǒng)內(nèi)存也是其中一個限制,。因?yàn)橛螛?biāo)其實(shí)是相當(dāng)于把磁盤數(shù)據(jù)整體放入了內(nèi)存中,,如果游標(biāo)數(shù)據(jù)量大則會造成內(nèi)存不足,內(nèi)存不足帶來的影響大家都知道了,。所以,,在數(shù)據(jù)量小比較小的情況才去使用游標(biāo)。但不建議使用游標(biāo),,可以通過從編程語言等方式實(shí)現(xiàn)相應(yīng)的業(yè)務(wù)邏輯,。 IT技術(shù)分享社區(qū) 個人博客網(wǎng)站:https://
|