盡量避免使用游標(biāo),因為游標(biāo)的效率較差,如果游標(biāo)操作的數(shù)據(jù)超過1萬行,那么就應(yīng)該考慮改寫。
創(chuàng)新互聯(lián)公司長期為近1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊從業(yè)經(jīng)驗10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為海東企業(yè)提供專業(yè)的做網(wǎng)站、網(wǎng)站設(shè)計,海東網(wǎng)站改版等技術(shù)服務(wù)。擁有十多年豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
使用基于游標(biāo)的方法之前,應(yīng)先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。
最好的改進(jìn)光標(biāo)性能的技術(shù)就是:能避免時就避免使用游標(biāo)
若有時無法避免使用游標(biāo),則可以用如下技巧來優(yōu)化游標(biāo)的性能。
(1). 除非必要否則不要使用static/insensitive游標(biāo)。打開static游標(biāo)會造成所有的行都被拷貝到臨時表。這正是為什么它對變化不敏感的原因——它實際上是指向臨時數(shù)據(jù)庫表中的一個備份。很自然,結(jié)果集越大,聲明其上的static游標(biāo)就會引起越多的臨時數(shù)據(jù)庫的資源爭奪問題。
(2). 除非必要否則不要使用keyset游標(biāo)。和static游標(biāo)一樣,打開keyset游標(biāo)會創(chuàng)建臨時表。雖然這個表只包括基本表的一個關(guān)鍵字列(除非不存在唯一關(guān)鍵字),但是當(dāng)處理大結(jié)果集時還是會相當(dāng)大的。
(3). 當(dāng)處理單向的只讀結(jié)果集時,使用fast_forward代替forward_only。使用fast_forward定義一個forward_only,則read_only游標(biāo)具有一定的內(nèi)部性能優(yōu)化。
(4). 使用read_only關(guān)鍵字定義只讀游標(biāo)。這樣可以防止意外的修改,并且讓服務(wù)器了解游標(biāo)移動時不會修改行。
(5). 小心事務(wù)處理中通過游標(biāo)進(jìn)行的大量行修改。根據(jù)事務(wù)隔離級別,這些行在事務(wù)完成或回滾前會保持鎖定,這可能造成服務(wù)器上的資源爭奪。
(6). 小心動態(tài)光標(biāo)的修改,尤其是建在非唯一聚集索引鍵的表上的游標(biāo),因為他們會造成“Halloween”問題——對同一行或同一行的重復(fù)的錯誤的修改。因為SQL Server在內(nèi)部會把某行的關(guān)鍵字修改成一個已經(jīng)存在的值,并強(qiáng)迫服務(wù)器追加下標(biāo),使它以后可以再結(jié)果集中移動。當(dāng)從結(jié)果集的剩余項中存取時,又會遇到那一行,然后程序會重復(fù),結(jié)果造成死循環(huán)。
(7). 對于大結(jié)果集要考慮使用異步游標(biāo),盡可能地把控制權(quán)交給調(diào)用者。當(dāng)返回相當(dāng)大的結(jié)果集到可移動的表格時,異步游標(biāo)特別有用,因為它們允許應(yīng)用程序幾乎馬上就可以顯示行
在end之前加上這個select (@mysql)。執(zhí)行存儲過程后會顯示執(zhí)行了哪些,哪些沒執(zhí)行到
樓上你的,你說的是oracle的,不是sqlserver的
游標(biāo)(Cursor)是處理數(shù)據(jù)的一種方法,為了查看或者處理結(jié)果集中的數(shù)據(jù),游標(biāo)提供了在結(jié)果集中一次以行或者多行前進(jìn)或向后瀏覽數(shù)據(jù)的能力。我們可以把游標(biāo)當(dāng)作一個指針,它可以指定結(jié)果中的任何位置,然后允許用戶對指定位置的數(shù)據(jù)進(jìn)行處理。
1.游標(biāo)的組成
游標(biāo)包含兩個部分:一個是游標(biāo)結(jié)果集、一個是游標(biāo)位置。
游標(biāo)結(jié)果集:定義該游標(biāo)得SELECT語句返回的行的集合。游標(biāo)位置:指向這個結(jié)果集某一行的當(dāng)前指針。
2.游標(biāo)的分類
游標(biāo)共有3類:API服務(wù)器游標(biāo)、Transaction-SQL游標(biāo)和API客戶端游標(biāo)。
其中前兩種游標(biāo)都是運行在服務(wù)器上的,所以又叫做服務(wù)器游標(biāo)。
API服務(wù)器游標(biāo)
API服務(wù)器游標(biāo)主要應(yīng)用在服務(wù)上,當(dāng)客戶端的應(yīng)用程序調(diào)用API游標(biāo)函數(shù)時,服務(wù)器會對API函數(shù)進(jìn)行處理。使用API函數(shù)和方法可以實現(xiàn)如下功能:
(1)打開一個連接。
(2)設(shè)置定義游標(biāo)特征的特性或?qū)傩?,API自動將游標(biāo)影射到每個結(jié)果集。
(3)執(zhí)行一個或多個Transaction-SQL語句。
(4)使用API函數(shù)或方法提取結(jié)果集中的行。
API服務(wù)器游標(biāo)包含以下四種:靜態(tài)游標(biāo)、動態(tài)游標(biāo)、只進(jìn)游標(biāo)、鍵集驅(qū)動游標(biāo)(Primary key)
靜態(tài)游標(biāo)的完整結(jié)果集將打開游標(biāo)時建立的結(jié)果集存儲在臨時表中,(靜態(tài)游標(biāo)始終是只讀的)。靜態(tài)游標(biāo)具有以下特點:總是按照打開游標(biāo)時的原樣顯示結(jié)果集;不反映數(shù)據(jù)庫中作的任何修改,也不反映對結(jié)果集行的列值所作的更改;不顯示打開游標(biāo)后在數(shù)據(jù)庫中新插入的行;組成結(jié)果集的行被其他用戶更新,新的數(shù)據(jù)值不會顯示在靜態(tài)游標(biāo)中;但是靜態(tài)游標(biāo)會顯示打開游標(biāo)以后從數(shù)據(jù)庫中刪除的行。
動態(tài)游標(biāo)與靜態(tài)游標(biāo)相反,當(dāng)滾動游標(biāo)時動態(tài)游標(biāo)反映結(jié)果集中的所有更改。結(jié)果集中的行數(shù)據(jù)值、順序和成員每次提取時都會改變。
只進(jìn)游標(biāo)不支持滾動,它只支持游標(biāo)從頭到尾順序提取數(shù)據(jù)行。注意:只進(jìn)游標(biāo)也反映對結(jié)果集所做的所有更改。
鍵集驅(qū)動游標(biāo)同時具有靜態(tài)游標(biāo)和動態(tài)游標(biāo)的特點。當(dāng)打開游標(biāo)時,該游標(biāo)中的成員以及行的順序是固定的,鍵集在游標(biāo)打開時也會存儲到臨時工作表中,對非鍵集列的數(shù)據(jù)值的更改在用戶游標(biāo)滾動的時候可以看見,在游標(biāo)打開以后對數(shù)據(jù)庫中插入的行是不可見的,除非關(guān)閉重新打開游標(biāo)。
Transaction-SQL游標(biāo)
該游標(biāo)是基于Declare Cursor 語法,主要用于Transaction-SQL腳本、存儲過程以及觸發(fā)器中。Transaction-SQL游標(biāo)在服務(wù)器處理由客戶端發(fā)送到服務(wù)器的Transaction-SQL語句。
在存儲過程或觸發(fā)器中使用Transaction-SQL游標(biāo)的過程為:
(1)聲明Transaction-SQL變量包含游標(biāo)返回的數(shù)據(jù)。為每個結(jié)果集列聲明一個變量。聲明足夠大的變量來保存列返回的值,并聲明變量的類型為可從數(shù)據(jù)類型隱式轉(zhuǎn)換得到的數(shù)據(jù)類型。
(2)使用Declare Cursor語句將Transaction-SQL游標(biāo)與Select語句相關(guān)聯(lián)。還可以利用Declare Cursor定義游標(biāo)的只讀、只進(jìn)等特性?!?/p>
(3)使用Open語句執(zhí)行Select語句填充游標(biāo)。
(4)使用Fetch Into語句提取單個行,并將每列中得數(shù)據(jù)移至指定的變量中。注意:其他Transaction-SQL語句可以引用那些變量來訪問提取的數(shù)據(jù)值。Transaction-SQL游標(biāo)不支持提取行塊。
(5)使用Close語句結(jié)束游標(biāo)的使用。注意:關(guān)閉游標(biāo)以后,該游標(biāo)還是存在,可以使用Open命令打開繼續(xù)使用,只有調(diào)用Deallocate語句才會完全釋放。
客戶端游標(biāo)
該游標(biāo)將使用默認(rèn)結(jié)果集把整個結(jié)果集高速緩存在客戶端上,所有的游標(biāo)操作都在客戶端的高速緩存中進(jìn)行。注意:客戶端游標(biāo)只支持只進(jìn)和靜態(tài)游標(biāo)。不支持其他游標(biāo)。
3.游標(biāo)的生命周期
游標(biāo)的生命周期包含有五個階段:聲明游標(biāo)、打開游標(biāo)、讀取游標(biāo)數(shù)據(jù)、關(guān)閉游標(biāo)、釋放游標(biāo)。
聲明游標(biāo)是為游標(biāo)指定獲取數(shù)據(jù)時所使用的Select語句,聲明游標(biāo)并不會檢索任何數(shù)據(jù),它只是為游標(biāo)指明了相應(yīng)的Select 語句。
Declare 游標(biāo)名稱 Cursor 參數(shù)
聲明游標(biāo)的參數(shù)
(1)Local與Global:Local表示游標(biāo)的作用于僅僅限于其所在的存儲過程、觸發(fā)器以及批處理中、執(zhí)行完畢以后游標(biāo)自動釋放。Global表示的是該游標(biāo)作用域是整個會話層。由連接執(zhí)行的任何存儲過程、批處理等都可以引用該游標(biāo)名稱,僅在斷開連接時隱性釋放。
(2)Forward_only與Scroll:前者表示為只進(jìn)游標(biāo),后者表示為可以隨意定位。默認(rèn)為前者。
(3)Static、Keyset與Dynamic: 第一個表示定義一個游標(biāo),其數(shù)據(jù)存放到一個臨時表內(nèi),對游標(biāo)的所有請求都從臨時表中應(yīng)答,因此,對該游標(biāo)進(jìn)行提取操作時返回的數(shù)據(jù)不反映對基表所作的修改,并且該游標(biāo)不允許修改。Keyset表示的是,當(dāng)游標(biāo)打開時,鍵集驅(qū)動游標(biāo)中行的身份與順序是固定的,并把其放到臨時表中。Dynamic表示的是滾動游標(biāo)時,動態(tài)游標(biāo)反映對結(jié)果集內(nèi)所有數(shù)據(jù)的更改。
(4)Read_only 、Scroll_Locks與Optimistic:第一個表示的是只讀游標(biāo),第二個表示的是在使用的游標(biāo)結(jié)果集數(shù)據(jù)上放置鎖,當(dāng)行讀取到游標(biāo)中然后對它們進(jìn)行修改時,數(shù)據(jù)庫將鎖定這些行,以保證數(shù)據(jù)的一致性。Optimistic的含義是游標(biāo)將數(shù)據(jù)讀取以后,如果這些數(shù)據(jù)被更新了,則通過游標(biāo)定位進(jìn)行的更新與刪除操作將不會成功。
標(biāo)準(zhǔn)游標(biāo):
Declare MyCursor Cursor
For Select * From Master_Goods
只讀游標(biāo)
Declare MyCusror Cursor
For Select * From Master_Goods
For Read Only
可更新游標(biāo)
Declare MyCusror Cursor
For Select * From Master_Goods
For UpDate
打開游標(biāo)使用Open語句用于打開Transaction-SQL服務(wù)器游標(biāo),執(zhí)行Open語句的過程中就是按照Select語句進(jìn)行填充數(shù)據(jù),打開游標(biāo)以后游標(biāo)位置在第一行。
打開游標(biāo)
全局游標(biāo):Open Global MyCursor 局部游標(biāo): Open MyCursor
讀取游標(biāo)數(shù)據(jù):在打開游標(biāo)以后,使用Fetch語句從Transaction-SQL服務(wù)器游標(biāo)中檢索特定的一行。使用Fetch操作,可以使游標(biāo)移動到下一個記錄,并將游標(biāo)返回的每個列得數(shù)據(jù)分別賦值給聲明的本地變量。
Fetch [Next | Prior | First | Last | Absolute n | Relative n ] From MyCursor
Into @GoodsID,@GoodsName
其中:Next表示返回結(jié)果集中當(dāng)前行的下一行記錄,如果第一次讀取則返回第一行。默認(rèn)的讀取選項為Next
Prior表示返回結(jié)果集中當(dāng)前行的前一行記錄,如果第一次讀取則沒有行返回,并且把游標(biāo)置于第一行之前。
First表示返回結(jié)果集中的第一行,并且將其作為當(dāng)前行。
Last表示返回結(jié)果集中的最后一行,并且將其作為當(dāng)前行。
Absolute n 如果n為正數(shù),則返回從游標(biāo)頭開始的第n行,并且返回行變成新的當(dāng)前行。如果n為負(fù),則返回從游標(biāo)末尾開始的第n行,并且返回行為新的當(dāng)前行,如果n為0,則返回當(dāng)前行。
Relative n 如果n為正數(shù),則返回從當(dāng)前行開始的第n行,如果n為負(fù),則返回從當(dāng)前行之前的第n行,如果為0,則返回當(dāng)前行。
關(guān)閉游標(biāo)調(diào)用的是Close語句,方式如下:Close Global MyCursor Close MyCursor
釋放游標(biāo)調(diào)用的是Deallocate語句,方法如下:Deallocate Glboal MyCursor Deallocate MyCursor
游標(biāo)實例:
Declare MyCusror Cursor Scroll
For Select * From Master_Goods Order By GoodsID
Open MyCursor
Fetch next From MyCursor
Into @GoodsCode,@GoodsName
While(@@Fetch_Status = 0)
Begin
Begin
Select @GoodsCode = Convert(Char(20),@GoodsCode)
Select @GoodsName = Convert(Char(20),@GoodsName)
PRINT @GoodsCode + ':' + @GoodsName
End
Fetch next From MyCursor
Into @GoodsCode,@GoodsName
End
Close MyCursor
Deallocate MyCursor
修改當(dāng)前游標(biāo)的數(shù)據(jù)方法如下:
UpDate Master_Goods Set GoodsName = 'yangyang8848' Where Current Of MyCursor;
刪除當(dāng)前游標(biāo)行數(shù)據(jù)的方法如下:
Delete From Master_Goods Where Current Of MyCursor
Select @@CURSOR_ROWS 可以得到當(dāng)前游標(biāo)中存在的數(shù)據(jù)行數(shù)。注意:此變量為一個連接上的全局變量,因此只對應(yīng)最后一次打開的游標(biāo)。
--申明一個游標(biāo)
DECLARE MyCursor CURSOR
FOR SELECT TOP 5 FBookName,FBookCoding FROM TBookInfo
--打開一個游標(biāo)
OPEN MyCursor
--循環(huán)一個游標(biāo)
DECLARE @BookName nvarchar(2000),@BookCoding nvarchar(2000)
FETCH NEXT FROM MyCursor INTO @BookName,@BookCoding
WHILE @@FETCH_STATUS =0
BEGIN
print 'name'+@BookName
FETCH NEXT FROM MyCursor INTO @BookName,@BookCoding
END
--關(guān)閉游標(biāo)
CLOSE MyCursor
--釋放資源
DEALLOCATE MyCursor
游標(biāo)屬于行級操作 消耗很大
SQL查詢是基于數(shù)據(jù)集的
所以一般查詢能有 能用數(shù)據(jù)集 就用數(shù)據(jù)集 別用游標(biāo)
數(shù)據(jù)量大 是性能殺手
游標(biāo)分類
滾動游標(biāo):游標(biāo)的位置可以來回移動,可在活動集中取任意元組。
非滾動游標(biāo):只能在活動集中順序地取下一個元組。
更新游標(biāo):數(shù)據(jù)庫對游標(biāo)指向的當(dāng)前行加鎖,當(dāng)程序讀下一行數(shù)據(jù)時,本行數(shù)據(jù)解鎖,下一行數(shù)據(jù)加鎖。
分享標(biāo)題:SQLServer游標(biāo)鎖,sql游標(biāo)的定義
網(wǎng)頁網(wǎng)址:http://jinyejixie.com/article36/dsdgosg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管、Google、營銷型網(wǎng)站建設(shè)、網(wǎng)站改版、軟件開發(fā)、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)