SQL SERVER 参考:游标(Cursor)的讲解与实例
當(dāng)決定對(duì)結(jié)果集進(jìn)行處理時(shí),必須聲明一個(gè)指向該結(jié)果集的游標(biāo)。如果曾經(jīng)用 C 語(yǔ)言寫(xiě)過(guò)對(duì)文件進(jìn)行處理的程序,那么游標(biāo)就像您打開(kāi)文件所得到的文件句柄一樣,只要文件打開(kāi)成功,該文件句柄就可代表該文件。對(duì)于游標(biāo)而言,其道理是相同的。可見(jiàn)游標(biāo)能夠?qū)崿F(xiàn)按與傳統(tǒng)程序讀取平面文件類(lèi)似的方式處理來(lái)自基礎(chǔ)表的結(jié)果集,從而把表中數(shù)據(jù)以平面文件的形式呈現(xiàn)給程序。
我們知道關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)實(shí)質(zhì)是面向集合的,在MS SQL SERVER 中并沒(méi)有一種描述表中單一記錄的表達(dá)形式,除非使用where 子句來(lái)限制只有一條記錄被選中。因此我們必須借助于游標(biāo)來(lái)進(jìn)行面向單條記錄的數(shù)據(jù)處理。
????
由此可見(jiàn),游標(biāo)允許應(yīng)用程序?qū)Σ樵?xún)語(yǔ)句select 返回的行結(jié)果集中每一行進(jìn)行相同或不同的操作,而不是一次對(duì)整個(gè)結(jié)果集進(jìn)行同一種操作;它還提供對(duì)基于游標(biāo)位置而對(duì)表中數(shù)據(jù)進(jìn)行刪除或更新的能力;而且,正是游標(biāo)把作為面向集合的數(shù)據(jù)庫(kù)管理系統(tǒng)和面向行的程序設(shè)計(jì)兩者聯(lián)系起來(lái),使兩個(gè)數(shù)據(jù)處理方式能夠進(jìn)行溝通。
每一個(gè)游標(biāo)必須有四個(gè)組成部分這四個(gè)關(guān)鍵部分必須符合下面的順序;
1.DECLARE 游標(biāo)
2.OPEN 游標(biāo)
3.從一個(gè)游標(biāo)中FETCH 信息
4.CLOSE 或DEALLOCATE 游標(biāo)
通常我們使用DECLARE 來(lái)聲明一個(gè)游標(biāo)聲明一個(gè)游標(biāo)主要包括以下主要內(nèi)容:
游標(biāo)名字
數(shù)據(jù)來(lái)源(表和列)
選取條件
屬性(僅讀或可修改)
其語(yǔ)法格式如下:
FOR select_statement
[FOR {READ ONLY | UPDATE [OF column_name [,...n]]}]
其中:
cursor_name 指游標(biāo)的名字。
INSENSITIVE
表明MS SQL SERVER 會(huì)將游標(biāo)定義所選取出來(lái)的數(shù)據(jù)記錄存放在一臨時(shí)表內(nèi)(建立在tempdb 數(shù)據(jù)庫(kù)下)。對(duì)該游標(biāo)的讀取操作皆由臨時(shí)表來(lái)應(yīng)答。因此,對(duì)基本表的修改并不影響游標(biāo)提取的數(shù)據(jù),即游標(biāo)不會(huì)隨著基本表內(nèi)容的改變而改變,同時(shí)也無(wú)法通過(guò)游標(biāo)來(lái)更新基本表。如果不使用該保留字,那么對(duì)基本表的更新、刪除都會(huì)反映到游標(biāo)中。
游標(biāo)指針示意圖
詳細(xì):
1.定義一個(gè)標(biāo)準(zhǔn)游標(biāo):
declare mycursor cursor for select * from yuangong2.定義一個(gè)只讀游標(biāo):
declare mycursor cursor for select * from yuangong for read only3.定義一個(gè)可寫(xiě)游標(biāo):
declare mycursor1 cursor for select * from yuangong for update of姓名,性別,年齡,基本工資,獎(jiǎng)金,所得稅,應(yīng)發(fā)工資
注: scroll 只能對(duì)只讀游標(biāo)起作用
4.打開(kāi)游標(biāo):open 游標(biāo)名
如:
declare mycursor cursor for select * from yuangongopen mycursor
5.從游標(biāo)中取數(shù)據(jù):fetch,默認(rèn)情況下,指針指向第一條記錄之前
移動(dòng)記錄指針的方法:
NEXT?? 下移一條記錄
prior 上移一條記錄
first 第一條記錄
LAST?? 最后一條記錄
absolute n 絕對(duì)記錄 第N條記錄
取數(shù)據(jù)語(yǔ)法:
fetch next|prior|first|last|absolute n????from 游標(biāo)名 [into 變量名列表]6.關(guān)閉游標(biāo): close 游標(biāo)名
暫時(shí)關(guān)閉游標(biāo),還可再使用OPEN打開(kāi).
7.釋放游標(biāo): deallocate 游標(biāo)名
從內(nèi)存中清除游標(biāo).如果還想使用,必須再次聲明.
對(duì)當(dāng)前游標(biāo)狀態(tài)進(jìn)行判斷:
8. @@fetch_status 如果返回是0,說(shuō)明當(dāng)前操作是成功的.否則是失敗的.
0 FETCH 語(yǔ)句成功。
-1 FETCH 語(yǔ)句失敗或此行不在結(jié)果集中。
-2 被提取的行不存在。
舉例1:
利用游標(biāo)從學(xué)生表中逐條讀取所有數(shù)據(jù):
declare @i INTDECLARE @TN CHAR(8),@FU CHAR(20)
declare mycursor cursor for select sno,sname from student
open mycursor
select @i=count(*) from student
while @@fetch_status=0 and @i>1
BEGIN
????fetch next from mycursor INTO @TN,@FU
????set @i=@i-1
PRINT @TN + ' ' + @FU
END
close mycursor
deallocate mycursor
結(jié)果:
s1001??? Jack Dong??????????
s1002??? Lucy Dong??????????
s1003??? Brezse Dong????????
s1004??? Andy Liu???????????
s1005??? Jack Chen??
舉例2:
通過(guò)游標(biāo)對(duì)讀取的數(shù)據(jù)進(jìn)行操作,并輸出不同的結(jié)果:
declare @s_name varchar(20),@c_name VARCHAR(64),@sc_core intdeclare my_cur cursor for select sname,cname,scgrade
from student s, course c, studentCourse sc WHERE s.sno=sc.sno AND c.cno=sc.cno
open my_cur
print space(27)+'2007年計(jì)算機(jī)專(zhuān)業(yè)考試系統(tǒng)'
fetch next from my_cur into @s_name,@c_name,@sc_core
while @@fetch_status=0
begin
????if @sc_core<60
????begin
????????print space(20)+@s_name+ @c_name +':不及格 '
????end
????else
????begin
?????????? if @sc_core >=60 and @sc_core <70
?????????? begin
?????????????? print space(20)+@s_name??+ @c_name +':及格 '
?????????? end
?????????? else
?????????? begin
?????????????? if @sc_core>=70 and @sc_core<80
?????????????? begin
??????????????????print space(20)+@s_name + @c_name +':良好'
?????????????? end
?????????????? else
?????????????? begin
??????????????????print space(20)+@s_name + @c_name +':優(yōu)秀'
?????????????? end
?????????? end
????end
fetch next from my_cur into @s_name,@c_name,@sc_core
end
close my_cur
deallocate my_cur
結(jié)果:
???????????????????????????? 2007年計(jì)算機(jī)專(zhuān)業(yè)考試系統(tǒng)
??????????????????? Jack Dong?????????????????????????????? C++ 程序設(shè)計(jì):及格
??????????????????? Jack Dong?????????????????????????????? 操作系統(tǒng):良好
??????????????????? Lucy Dong?????????????????????????????? C++ 程序設(shè)計(jì):優(yōu)秀
??????????????????? Lucy Dong?????????????????????????????? 計(jì)算機(jī)組成原理:良好
??????????????????? Brezse Dong???????????????????????????? C++ 程序設(shè)計(jì):優(yōu)秀
??????????????????? Brezse Dong???????????????????????????? 面向?qū)ο蟮某绦蛟O(shè)計(jì)方法:不及格
??????????????????? Andy Liu??????????????????????????????? 操作系統(tǒng):不及格
??????????????????? Andy Liu??????????????????????????????? 計(jì)算機(jī)組成原理:優(yōu)秀
使用游標(biāo)時(shí)應(yīng)注意的問(wèn)題:
(1) 盡管使用游標(biāo)比較靈活,可以實(shí)現(xiàn)對(duì)數(shù)據(jù)集中單行數(shù)據(jù)的直接操作,但游標(biāo)會(huì)在下面幾個(gè)方面影響系統(tǒng)的性能:
-使用游標(biāo)會(huì)導(dǎo)致頁(yè)鎖與表鎖的增加
-導(dǎo)致網(wǎng)絡(luò)通信量的增加
-增加了服務(wù)器處理相應(yīng)指令的額外開(kāi)銷(xiāo)
(2) 使用游標(biāo)時(shí)的優(yōu)化問(wèn)題:
-明確指出游標(biāo)的用途:for read only或for update
-在for update后指定被修改的列
總結(jié)
以上是生活随笔為你收集整理的SQL SERVER 参考:游标(Cursor)的讲解与实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Altiris™ IT Manageme
- 下一篇: 梦到掉光了牙齿是什么预兆