(一)淺談?dòng)螛?biāo)
(1)游標(biāo)的概念
游標(biāo)是指向查詢結(jié)果集的一個(gè)指針,它是一個(gè)通過(guò)定義語(yǔ)句與一條Select語(yǔ)句相關(guān)聯(lián)的一組SQL語(yǔ)句,即從結(jié)果集中逐一的讀取一條記錄。游標(biāo)包含兩方面的內(nèi)容:
●游標(biāo)結(jié)果集:執(zhí)行其中的Select語(yǔ)句所得到的結(jié)果集;
●游標(biāo)位置:一個(gè)指向游標(biāo)結(jié)果集內(nèi)的某一條記錄的指針
利用游標(biāo)可以單獨(dú)操縱結(jié)果集中的每一行。游標(biāo)在定義以后存在兩種狀態(tài):關(guān)閉和打開(kāi)。當(dāng)游標(biāo)關(guān)閉時(shí),其查詢結(jié)果集不存在;只有當(dāng)游標(biāo)打開(kāi)時(shí),才能按行讀取或修改結(jié)果集中的數(shù)據(jù)。
(2)淺談?dòng)螛?biāo)
游標(biāo)我們可以通俗的解釋為變動(dòng)的標(biāo)示。正如它的解釋一樣,數(shù)據(jù)庫(kù)中的游標(biāo)其實(shí)也是一種讀取數(shù)據(jù)的方式。舉個(gè)簡(jiǎn)單的例子來(lái)說(shuō):我有一個(gè)電話本,電話本上的號(hào)碼首先是按地域劃分的,現(xiàn)在我想找個(gè)家住廊坊的李四。首先我們要做的是先找到廊坊地區(qū)的電話表,找到后的表也即是我們上面所說(shuō)的游標(biāo)結(jié)果集;而為了找到李四我們可能會(huì)用手一條一條逐行的掃過(guò),以幫助我們找到所需的那條記錄。對(duì)應(yīng)于數(shù)據(jù)庫(kù)來(lái)說(shuō),這就是游標(biāo)的模型。所以,你可以這樣想象:表格是數(shù)據(jù)庫(kù)中的表,而我們的手好比是游標(biāo)。
總結(jié)來(lái)說(shuō)游標(biāo)就好比是在電話本上逐一掃描號(hào)碼的手指。
(二)使用游標(biāo)
一個(gè)應(yīng)用程序中可以使用兩種類型的游標(biāo):前端(客戶)游標(biāo)和后端(服務(wù)器)游標(biāo),它們是兩個(gè)不同的概念。
但無(wú)論使用哪種游標(biāo),都必須經(jīng)過(guò)如下的步驟:
●聲明游標(biāo)
●打開(kāi)游標(biāo)
●從游標(biāo)中操作數(shù)據(jù)
●關(guān)閉游標(biāo)
下面我們主要講述下服務(wù)器游標(biāo):
(1)定義游標(biāo)
使用游標(biāo)之前必須先聲明它。聲明指定定義游標(biāo)結(jié)果集的查詢。通過(guò)使用for update或for read only關(guān)鍵詞將游標(biāo)顯式定義成可更新的或只讀的。
Declare cursor_name cursor
For select_statement
[for{read only|update[of colum_name_list]}]
舉例:
Declare company_crsr cursor
For select name,salary from company where salary>2000
For update of name,salary
上面我們聲明了一個(gè)名為company_crsr的游標(biāo)。
(2)打開(kāi)游標(biāo)
open的語(yǔ)法為:
open 游標(biāo)名
在聲明游標(biāo)后,必須打開(kāi)它以便用fetch,update,delete讀取、修改、刪除行。在打開(kāi)一個(gè)游標(biāo)后,它將被放在游標(biāo)結(jié)果集的首行前,必須用fetch語(yǔ)句訪問(wèn)該首行。
(3)讀取游標(biāo)數(shù)據(jù)
在聲明并打開(kāi)一個(gè)游標(biāo)后,可用fetch命令從游標(biāo)結(jié)果集中獲取數(shù)據(jù)行。
Fetch的語(yǔ)法為:
Fetch [[Next | Prior | First | Last | Absolute{n|@nvar} |Relative {n|@nvar}]
From] 游標(biāo)名 [into 變量列表]
參數(shù)說(shuō)明:
Next:返回結(jié)果集中當(dāng)前行的下一行,如果該語(yǔ)句是第一次讀取結(jié)果集中數(shù)據(jù)則返回的是第一行
Prior:返回結(jié)果集中當(dāng)前行的上一行,如果該語(yǔ)句是第一次讀取結(jié)果集中的數(shù)據(jù)則無(wú)記錄結(jié)果返回并把游標(biāo)位置設(shè)置為第一行。
First:返回游標(biāo)第一行;Last:返回游標(biāo)中的最后一行;
Absolute{n|@nvar}:如果 n 或 @nvar 為正數(shù),返回從游標(biāo)頭開(kāi)始的第 n 行并將返回的行變成新的當(dāng)前行。如果 n 或 @nvar 為負(fù)數(shù),返回游標(biāo)尾之前的第 n 行并將返回的行變成新的當(dāng)前行。如果 n 或 @nvar 為 0,則沒(méi)有行返回。n 必須為整型常量且 @nvar 必須為smallint、tinyint 或 int。
RELATIVE {n | @nvar}:如果 n 或 @nvar 為正數(shù),返回當(dāng)前行之后的第 n 行并將返回的行變成新的當(dāng)前行。如果 n 或 @nvar 為負(fù)數(shù),返回當(dāng)前行之前的第 n 行并將返回的行變成新的當(dāng)前行。如果 n 或 @nvar 為 0,返回當(dāng)前行。如果對(duì)游標(biāo)的第一次提取操作時(shí)將FETCH RELATIVE 的 n 或 @nvar 指定為負(fù)數(shù)或 0,則沒(méi)有行返回。n 必須為整型常量且@nvar 必須為 smallint、tinyint 或 int。
舉例:
Fetch next
company_crsr into @name,@salary
SQL Server在每次讀取后返回一個(gè)狀態(tài)值。可用@@sql_status訪問(wèn)該值,下表給出了可能的@@sql_status值及其意義。
值意義:
0——Fetch語(yǔ)句成功
1——Fetch語(yǔ)句導(dǎo)致一錯(cuò)誤
2——結(jié)果集沒(méi)有更多的數(shù)據(jù),當(dāng)前位置位于結(jié)果集最后一行,而客戶對(duì)該游標(biāo)仍發(fā)出Fetch語(yǔ)句時(shí)。
若游標(biāo)是可更新的,可用update和delete語(yǔ)句來(lái)更新和刪除行。
刪除游標(biāo)當(dāng)前行的語(yǔ)法為:
Delete [from] 表名
where current of 游標(biāo)名
舉例:delete from authors where current of authors_crsr
當(dāng)游標(biāo)刪除一行后,SQL Server將游標(biāo)置于被刪除行的前一行上。
更新游標(biāo)當(dāng)前行的語(yǔ)法為:
update 表名
set column_name1={expression1|NULL|(select_statement)}
[,column_name2={expression2|NULL|(select_statement)}
[……]
where current of 游標(biāo)名
舉例:
update company
set name=”張三”,salary=”5000”
where current of company_crsr
(4)關(guān)閉游標(biāo)
當(dāng)結(jié)束一個(gè)游標(biāo)結(jié)果集時(shí),可用close關(guān)閉。該語(yǔ)法為:
close 游標(biāo)名
關(guān)閉游標(biāo)并不改變其定義,可用open再次打開(kāi)。若想放棄游標(biāo),必須使用deallocate釋放它,deallocater的語(yǔ)法為:
deallocater cursor 游標(biāo)名
deallocater語(yǔ)句通知SQL Server釋放Declare語(yǔ)句使用的共享內(nèi)存,不再允許另一進(jìn)程在其上執(zhí)行Open操作。