SQL中游標(biāo)的語(yǔ)法及應(yīng)用
游標(biāo)是SQL數(shù)據(jù)庫(kù)中不可或缺的部分,可以旋轉(zhuǎn)儲(chǔ)存在系統(tǒng)永久表中的數(shù)據(jù)行的副本,下面就將為您詳解游標(biāo)的使用,以及語(yǔ)法,供您參考學(xué)習(xí)。
MS-SQL的游標(biāo)是一種臨時(shí)的數(shù)據(jù)庫(kù)對(duì)象,既對(duì)可用來(lái)旋轉(zhuǎn)儲(chǔ)存在系統(tǒng)永久表中的數(shù)據(jù)行的副本,也可以指向儲(chǔ)存在系統(tǒng)永久表中的數(shù)據(jù)行的指針。
游標(biāo)為您提供了在逐行的基礎(chǔ)上而不是一次處理整個(gè)結(jié)果集為基礎(chǔ)的操作表中數(shù)據(jù)的方法。
1.如何使用游標(biāo)
1) 定義游標(biāo)語(yǔ)句 Declare <游標(biāo)名> Cursor For
2) 創(chuàng)建游標(biāo)語(yǔ)句 Open <游標(biāo)名>
3) 提取游標(biāo)列值、移動(dòng)記錄指針 Fetch <列名列表> From <游標(biāo)名> [Into <變量列表>]
4) 使用@@Fetch_Status利用While循環(huán)處理游標(biāo)中的行
5) 刪除游標(biāo)并釋放語(yǔ)句 Close <游標(biāo)名>/Deallocate <游標(biāo)名>
6) 游標(biāo)應(yīng)用實(shí)例
--定義游標(biāo)
Declare cur_Depart Cursor
For Select cDeptID,cDeptName From Department into @DeptID,@DeptName
--創(chuàng)建游標(biāo)
Open cur_Depart
--移動(dòng)或提取列值
Fetch From cur_Depart into @DeptID,@DeptName
--利用循環(huán)處理游標(biāo)中的列值
While @@Fetch_Status=0
Begin
Print @DeptID,@DeptName
Fetch From cur_Depart into @DeptID,@DeptName
End
--關(guān)閉/釋放游標(biāo)
Close cur_Depart
Deallocate cur_Depart
簡(jiǎn)單的過(guò)程:
定義游標(biāo)
DECLARE CustomerCursor CURSOR FOR
SELECT acct_no,name,balance
FROM customer
WHERE province="北京";
打開(kāi)游標(biāo)
OPEN CustomerCursor;
提取數(shù)據(jù)--設(shè)置循環(huán)
lb_continue=True #p#
ll_total=0
DO WHILE lb_continue
FETCH CustomerCursor
INTO:ls_acct_no, :ls_name, :ll_balance;
If sqlca.sqlcode=0 Then
ll_total+=ll_balance
Else
lb_continue=False
End If
LOOP
關(guān)閉游標(biāo)
CLOSE CustomerCursor;
2.語(yǔ)句的詳細(xì)及注意
1) 定義游標(biāo)語(yǔ)句
Declare <游標(biāo)名> [Insensitive] [Scroll] Cursor
For
3.游標(biāo)使用技巧及注意
1) 利用Order By改變游標(biāo)中行的順序。此處應(yīng)該注意的是,只有在查詢的中Select 子句中出現(xiàn)的列才能作為Order by子句列,這一點(diǎn)與普通的Select語(yǔ)句不同;
2) 當(dāng)語(yǔ)句中使用了Order By子句后,將不能用游標(biāo)來(lái)執(zhí)行定位DELETE/UPDATE語(yǔ)句;如何解決這個(gè)問(wèn)題,首先在原表上創(chuàng)建索引,在創(chuàng)建游標(biāo)時(shí)指定使用此索引來(lái)實(shí)現(xiàn);例如:
Declare cur_Depart Cursor
For Select cDeptID,cDeptName From Department With INDEX(idx_ID)
For Update Of cDeptID,cDeptName
通過(guò)在From子句中增加With Index來(lái)實(shí)現(xiàn)利用索引對(duì)表的排序;
3) 在游標(biāo)中可以包含計(jì)算好的值作為列;
4) 利用@@Cursor_Rows確定游標(biāo)中的行數(shù) #p#
4.使用系統(tǒng)過(guò)程管理游標(biāo)
在建立一個(gè)游標(biāo)之后,便可利用系統(tǒng)過(guò)程對(duì)游標(biāo)進(jìn)行管理管理,游標(biāo)的系統(tǒng)過(guò)程主要有以下幾個(gè):sp_cursor_list、sp_describe_cursor、 sp_describe_cursor_tables 、sp_describe_cursor_columns。
1) sp_cursor_list 顯示在當(dāng)前作用域內(nèi)的游標(biāo)及其屬性。其命令格式為:
">sp_cursor_list [ @cursor_return = ] cursor_variable_name OUTPUT,
[ @cursor_scope = ] cursor_scope
參數(shù):
· [@cursor_return =] cursor_variable_name OUTPUT:聲明的游標(biāo)變量的名稱(chēng)。cursor_variable_name 的數(shù)據(jù)類(lèi)型為 cursor,沒(méi)有默認(rèn)值。游標(biāo)是可滾動(dòng)的、動(dòng)態(tài)的只讀游標(biāo)。
· [@cursor_scope =] cursor_scope:指定要報(bào)告的游標(biāo)級(jí)別。cursor_scope 的數(shù)據(jù)類(lèi)型為 int,沒(méi)有默認(rèn)值,可以是下列值中的一個(gè)。
值描述
1 報(bào)告所有本地游標(biāo)。
2 報(bào)告所有全局游標(biāo)。
3 報(bào)告本地游標(biāo)和全局游標(biāo)。
提示:由于sp_cursor_list是一個(gè)含有游標(biāo)類(lèi)型變量@cursor_return,且有OUTPUT保留字的系統(tǒng)過(guò)程,游標(biāo)變量@cursor_return中的結(jié)果集與pub_cur游標(biāo)中的結(jié)果集是不同的。
2) sp_describe_cursor 報(bào)告服務(wù)器游標(biāo)的特性。
sp_describe_cursor [ @cursor_return = ] output_cursor_variable OUTPUT
{ [ , [ @cursor_source = ] N''local''
, [ @cursor_identity = ] N''local_cursor_name'' ]
| [ , [ @cursor_source = ] N''global''
, [ @cursor_identity = ] N''global_cursor_name'' ]
| [ , [ @cursor_source = ] N''variable''
, [ @cursor_identity = ] N''input_cursor_variable'' ]
}
參數(shù):
· [@cursor_return =] output_cursor_variable OUTPUT:聲明游標(biāo)變量的名稱(chēng),該變量接收游標(biāo)輸出。output_cursor_variable 的數(shù)據(jù)類(lèi)型為 cursor,沒(méi)有默認(rèn)值。調(diào)用 sp_describe_cursor 時(shí),不能與任何游標(biāo)相關(guān)聯(lián)。返回的游標(biāo)是可滾動(dòng)的動(dòng)態(tài)只讀游標(biāo)。
· [@cursor_source =] { N''local'' | N''global'' | N''variable'' }:指定是使用本地游標(biāo)的名稱(chēng)、全局游標(biāo)的名稱(chēng)、還是游標(biāo)變量的名稱(chēng)來(lái)指定當(dāng)前正在對(duì)其進(jìn)行報(bào)告的游標(biāo)。參數(shù)是 nvarchar(30)。 #p#
· [@cursor_identity =] N''local_cursor_name'']:由具有 LOCAL 關(guān)鍵字或默認(rèn)設(shè)置為 LOCAL 的 DECLARE CURSOR 語(yǔ)句創(chuàng)建的游標(biāo)的名稱(chēng)。local_cursor_name 的數(shù)據(jù)類(lèi)型為 nvarchar(128)。
· [@cursor_identity =] N''global_cursor_name'']:由具有 GLOBAL 關(guān)鍵字或默認(rèn)設(shè)置為 GLOBAL 的 DECLARE CURSOR 語(yǔ)句創(chuàng)建的游標(biāo)的名稱(chēng)。也可以是由 ODBC 應(yīng)用程序打開(kāi)然后通過(guò)調(diào)用 SQLSetCursorName 對(duì)游標(biāo)命名的 API 服務(wù)器游標(biāo)的名稱(chēng)。global_cursor_name 的數(shù)據(jù)類(lèi)型為 nvarchar(128)。
· [@cursor_identity =] N''input_cursor_variable'']:與開(kāi)放游標(biāo)相關(guān)聯(lián)的游標(biāo)變量的名稱(chēng)。input_cursor_variable 的數(shù)據(jù)類(lèi)型為 nvarchar(128)。
提示: sp_descride_cursor_tables和sp_describe_cursor_columms的命令格式與sp_describe_cursor的命令格式一樣。
5.游標(biāo)種類(lèi)
MS SQL SERVER 支持三種類(lèi)型的游
標(biāo):Transact_SQL 游標(biāo),API 服務(wù)器游標(biāo)和客戶游標(biāo)。
1) Transact_SQL 游標(biāo)Transact_SQL 游標(biāo)是由DECLARE CURSOR 語(yǔ)法定義、主要用在Transact_SQL 腳本、存儲(chǔ)過(guò)程和觸發(fā)器中。Transact_SQL 游標(biāo)主要用在服務(wù)器上,由從客戶端發(fā)送給服務(wù)器的Transact_SQL 語(yǔ)句或是批處理、存儲(chǔ)過(guò)程、觸發(fā)器中的Transact_SQL 進(jìn)行管理。 Transact_SQL 游標(biāo)不支持提取數(shù)據(jù)塊或多行數(shù)據(jù)。
2) API 游標(biāo) API 游標(biāo)支持在OLE DB, ODBC 以及DB_library 中使用游標(biāo)函數(shù),主要用在服務(wù)器上。每一次客戶端應(yīng)用程序調(diào)用API 游標(biāo)函數(shù),MS SQL SEVER 的OLE DB 提供者、ODBC驅(qū)動(dòng)器或DB_library 的動(dòng)態(tài)鏈接庫(kù)(DLL) 都會(huì)將這些客戶請(qǐng)求傳送給服務(wù)器以對(duì)API游標(biāo)進(jìn)行處理。
3) 客戶游標(biāo) 客戶游標(biāo)主要是當(dāng)在客戶機(jī)上緩存結(jié)果集時(shí)才使用。在客戶游標(biāo)中,有一個(gè)缺省的結(jié)果集被用來(lái)在客戶機(jī)上緩存整個(gè)結(jié)果集??蛻粲螛?biāo)僅支持靜態(tài)游標(biāo)而非動(dòng)態(tài)游標(biāo)。由于服務(wù)器游標(biāo)并不支持所有的Transact-SQL 語(yǔ)句或批處理,所以客戶游標(biāo)常常僅被用作服務(wù)器游標(biāo)的輔助。因?yàn)樵谝话闱闆r下,服務(wù)器游標(biāo)能支持絕大多數(shù)的游標(biāo)操作。
由于API 游標(biāo)和Transact-SQL 游標(biāo)使用在服務(wù)器端,所以被稱(chēng)為服務(wù)器游標(biāo),也被稱(chēng)為后臺(tái)游標(biāo),而客戶端游標(biāo)被稱(chēng)為前臺(tái)游標(biāo)。在本章中我們主要講述服務(wù)器(后臺(tái))游標(biāo)。
select count(id) from info
select * from info
--清除所有記錄
truncate table info
declare @i int
set @i=1
while @i<1000000
begin
insert into info values(''Justin''+str(@i),''深圳''+str(@i))
set @i=@i+1
end #p#
6.游標(biāo)和游標(biāo)的優(yōu)點(diǎn)
在數(shù)據(jù)庫(kù)中,游標(biāo)是一個(gè)十分重要的概念。游標(biāo)提供了一種對(duì)從表中檢索出的數(shù)據(jù)進(jìn)行操作的靈活手段,就本質(zhì)而言,游標(biāo)實(shí)際上是一種能從包括多條數(shù)據(jù)記錄的結(jié)果集中每次提取一條記錄的機(jī)制。游標(biāo)總是與一條T_SQL 選擇語(yǔ)句相關(guān)聯(lián)因?yàn)橛螛?biāo)由結(jié)果集(可以是零條、一條或由相關(guān)的選擇語(yǔ)句檢索出的多條記錄)和結(jié)果集中指向特定記錄的游標(biāo)位置組成。當(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中并沒(méi)有一種描述表中單一記錄的表達(dá)形式,除非使用where 子句來(lái)限制只有一條記錄被選中。因此我們必須借助于游標(biāo)來(lái)進(jìn)行面向單條記錄的數(shù)據(jù)處理。 SERVER
由此可見(jiàn),游標(biāo)允許應(yīng)用程序?qū)Σ樵冋Z(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)行溝通。
以[master].[dbo].[spt_values] 這個(gè)表為例子
===
declare @name nvarchar(35)
declare @number int
declare my_cursor cursor for --定義游標(biāo)cursor1
select TOP 5 [name],[number] from [spt_values] --使用游標(biāo)的對(duì)象(跟據(jù)需要填入select文)
open my_cursor --打開(kāi)游標(biāo)
fetch next from my_cursor into @name,@number --將游標(biāo)向下移1行,獲取的數(shù)據(jù)放入之前定義的變量@id,@name中
while(@@fetch_status=0) --判斷是否成功獲取數(shù)據(jù)
begin
--update [spt_values] set [name]=@name+'1'
--where [number]=@number+1 --進(jìn)行相應(yīng)處理(跟據(jù)需要填入SQL文)
print @name
print @number
print '===='
fetch next from my_cursor into @name,@number --將游標(biāo)向下移1行
end
close my_cursor --關(guān)閉游標(biāo)
deallocate my_cursor
=====================以下是基礎(chǔ)
blog.csdn.net/lejuo/archive/2008/11/12/3279340.aspx
可百度 SQL游標(biāo)語(yǔ)法及舉例 進(jìn)行更深入學(xué)習(xí)
游標(biāo)的定義:
每一個(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) #p#
通常我們使用DECLARE 來(lái)聲明一個(gè)游標(biāo)聲明一個(gè)游標(biāo)主要包括以下主要內(nèi)容:
游標(biāo)名字
數(shù)據(jù)來(lái)源(表和列)
選取條件
屬性(僅讀或可修改)
其語(yǔ)法格式如下:
DECLARE cursor_name [INSENSITIVE] [SCROLL] CURSOR
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)中。
另外應(yīng)該指出,當(dāng)遇到以下情況發(fā)生時(shí),游標(biāo)將自動(dòng)設(shè)定INSENSITIVE 選項(xiàng)。
在SELECT 語(yǔ)句中使用DISTINCT、 GROUP BY、 HAVING UNION 語(yǔ)句;
使用OUTER JOIN;
所選取的任意表沒(méi)有索引;
將實(shí)數(shù)值當(dāng)作選取的列。
SCROLL
表 明所有的提取操作(如FIRST、 LAST、 PRIOR、 NEXT、 RELATIVE、 ABSOLUTE)都可用。如果不使用該保留字,那么只能進(jìn)行NEXT 提取操作。由此可見(jiàn),SCROLL 極大地增加了提取數(shù)據(jù)的靈活性,可以隨意讀取結(jié)果集中的任一行數(shù)據(jù)記錄,而不必關(guān)閉再
重開(kāi)游標(biāo)。
select_statement
是定義結(jié)果集的SELECT 語(yǔ)句。應(yīng)該注意的是,在游標(biāo)中不能使用COMPUTE、COMPU- TE BY、 FOR BROWSE、 INTO 語(yǔ)句。
READ ONLY
表明不允許游標(biāo)內(nèi)的數(shù)據(jù)被更新盡管在缺省狀態(tài)下游標(biāo)是允許更新的。而且在UPDATE或DELETE 語(yǔ)句的WHERE CURRENT OF 子句中,不允許對(duì)該游標(biāo)進(jìn)行引用。
UPDATE [OF column_name[,…n]]
定義在游標(biāo)中可被修改的列,如果不指出要更新的列,那么所有的列都將被更新。當(dāng)游標(biāo)被成功創(chuàng)。
【編輯推薦】