sql游標總結(jié)2010-05-04 13:36:55| 分類: oracle 開發(fā) | 標簽: |字號大中小 訂閱 游標的概念 (1)聲明游標。 (2)打開游標。 (3)從一個游標中查找信息。 (4)關(guān)閉游標。 (5)釋放游標。 1.SQL-92語法格式 語法: DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSOR FOR select_statement FOR { READ ON 參數(shù)說明: l DECLARE cursor_name:指定一個游標名稱,其游標名稱必須符合標識符規(guī)則。 l INSENSITIVE:定義一個游標,以創(chuàng)建將由該游標使用的數(shù)據(jù)的臨時復(fù)本。對游標的所有請求都從tempdb中的臨時表中得到應(yīng)答;因此,在對該游標進行提取操作時返回的數(shù)據(jù)中不反映對基表所做的修改,并且該游標不允許修改。使用SQL-92語法時,如果省略INSENSITIVE,(任何用戶)對基表提交的刪除和更新都反映在后面的提取中。 l SCROLL:指定所有的提取選項(FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE)均可用。 2 FIRST:取第一行數(shù)據(jù)。 2 LAST:取最后一行數(shù)據(jù)。 2 PRIOR:取前一行數(shù)據(jù)。 2 NEXT:取后一行數(shù)據(jù)。 2 RELATIVE:按相對位置取數(shù)據(jù)。 2 ABSOLUTE:按絕對位置取數(shù)據(jù)。 如果未指定SCROLL,則NEXT是惟一支持的提取選項。 l select_statement:定義游標結(jié)果集的標準SELECT語句。在游標聲明的select_statement內(nèi)不允許使用關(guān)鍵字COMPUTE、COMPUTE BY、FOR BROWSE和INTO。 l READ ON l UPDATE [ OF column_name [ ,...n ] ]:定義游標內(nèi)可更新的列。如果指定OF column_name [,...n]參數(shù),則只允許修改所列出的列。如果在UPDATE中未指定列的列表,則可以更新所有列。 2.SQL Server擴展格式 語法: DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] [ FORWARD_ON [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ON [ TYPE_WARNING ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] ] 參數(shù)說明: l DECLARE cursor_name:指定一個游標名稱,其游標名稱必須符合標識符規(guī)則。 l LOCAL:定義游標的作用域僅限在其所在的批處理、存儲過程或觸發(fā)器中。當建立游標在存儲過程執(zhí)行結(jié)束后,游標會被自動釋放。 l GLOBAL:指定該游標的作用域?qū)B接是全局的。在由連接執(zhí)行的任何存儲過程或批處理中,都可以引用該游標名稱。該游標僅在脫接時隱性釋放。 l FORWARD_ON l STATIC:定義一個游標,以創(chuàng)建將由該游標使用的數(shù)據(jù)的臨時復(fù)本。對游標的所有請求都從tempdb中的該臨時表中得到應(yīng)答;因此,在對該游標進行提取操作時返回的數(shù)據(jù)中不反映對基表所做的修改,并且該游標不允許修改。 l KEYSET:指定當游標打開時,游標中行的成員資格和順序已經(jīng)固定。對行進行惟一標識的鍵集內(nèi)置在tempdb內(nèi)一個稱為keyset的表中。對基表中的非鍵值所做的更改(由游標所有者更改或由其他用戶提交)在用戶滾動游標時是可視的。其他用戶進行的插入是不可視的(不能通過Transact-SQL服務(wù)器游標進行插入)。如果某行已刪除,則對該行的提取操作將返回@@FETCH_STATUS值-2。從游標外更新鍵值類似于刪除舊行后接著插入新行的操作。含有新值的行不可視,對含有舊值的行的提取操作將返回@@FETCH_STATUS值-2。如果通過指定WHERE CURRENT OF子句用游標完成更新,則新值可視。 l DYNAMIC:定義一個游標,以反映在滾動游標時對結(jié)果集內(nèi)的行所做的所有數(shù)據(jù)的更改。行的數(shù)據(jù)值、順序和成員在每次提取時都會更改。動態(tài)游標不支持ABSOLUTE提取選項。 l FAST_FORWARD:指明一個FORWARD_ON l SCROLL_LOCKS:指定確保通過游標完成的定位更新或定位刪除可以成功。將行讀入游標以確保它們可用于以后的修改時,SQL Server會鎖定這些行。如果還指定了FAST_FORWARD,則不能指定SCROLL_LOCKS。 l OPTIMISTIC:指明在數(shù)據(jù)被讀入游標后,如果游標中某行數(shù)據(jù)已發(fā)生變化,那么對游標數(shù)據(jù)進行更新或刪除可能會導(dǎo)致失敗。 l TYPE_WARNING:指定如果游標從所請求的類型隱性轉(zhuǎn)換為另一種類型,則給客戶端發(fā)送警告消息。 使用DECLARE CURSOR語句創(chuàng)建以下幾種形式的游標。 (1)示例:創(chuàng)建一個名為“MyCursor”的標準游標。 USE 銷售管理系統(tǒng) DECLARE MyCursor CURSOR FOR SELECT * FROM 操作員信息表 GO (2)示例:創(chuàng)建一個名為“MyCursor_01”的只讀游標。 USE 銷售管理系統(tǒng) DECLARE MyCursor_01 CURSOR FOR SELECT * FROM 操作員信息表 FOR READ ON GO (3)示例:創(chuàng)建一個名為“MyCursor_02”的更新游標。 USE 銷售管理系統(tǒng) DECLARE MyCursor_02 CURSOR FOR SELECT 操作員編號,操作員姓名,操作員年齡 FROM 操作員信息表 FOR UPDATE --更新游標 GO 打開游標 語法: OPEN { { [ GLOBAL ] cursor_name } | cursor_variable_name } 參數(shù)說明: l GLOBAL:指定cursor_name為全局游標。 l cursor_name:已聲明的游標名稱,如果全局游標和局部游標都使用cursor_name作為其名稱,那么如果指定了GLOBAL,cursor_name指的是全局游標,否則,cursor_name指的是局部游標。 l cursor_variable_name:游標變量的名稱,該名稱引用一個游標。 說明:如果使用INSENSITIV或STATIC選項聲明了游標,那么OPEN將創(chuàng)建一個臨時表以保留結(jié)果集。如果結(jié)果集中任意行的大小超過SQL Server表的最大行大小,OPEN將失敗。如果使用KEYSET選項聲明了游標,那么OPEN將創(chuàng)建一個臨時表以保留鍵集。臨時表存儲在tempdb中。 首先聲明一個名為MyCursor_001的游標,然后使用OPEN命令打開該游標。 操作步驟如下: (1)在操作系統(tǒng)中選擇“開始”→“所有程序”→“Microsoft SQL Server”→“查詢分析器”命令,打開查詢分析器。 (2)在查詢分析器的工具欄中選擇要連接的數(shù)據(jù)庫,這里選擇“銷售管理系統(tǒng)”。 (3)在代碼編輯區(qū)中編寫如下代碼。 SQL語句如下: USE 銷售管理系統(tǒng) DECLARE MyCursor_001 CURSOR FOR --聲明游標 SELECT 操作員編號,操作員姓名,操作員年齡 FROM 操作員信息表 WHERE 操作員編號 = 'CY20040604006' OPEN MyCursor_001 --打開游標 GO 語法: FETCH [ [ NEXT | PRIOR | FIRST | LAST | ABSOLUTE { n | @nvar } | RELATIVE { n | @nvar } ] FROM ] { { [ GLOBAL ] cursor_name } | @cursor_variable_name } [ INTO @variable_name [ ,...n ] ] 參數(shù)說明: l NEXT:返回緊跟當前行之后的結(jié)果行,并且當前行遞增為結(jié)果行。如果FETCH NEXT為對游標的第一次提取操作,則返回結(jié)果集中的第一行。NEXT為默認的游標提取選項。 l PRIOR:返回緊臨當前行前面的結(jié)果行,并且當前行遞減為結(jié)果行。如果FETCH PRIOR為對游標的第一次提取操作,則沒有行返回并且游標置于第一行之前。 l FIRST:返回游標中的第一行并將其作為當前行。 l LAST:返回游標中的最后一行并將其作為當前行。 l ABSOLUTE {n | @nvar}:如果n或@nvar為正數(shù),返回從游標頭開始的第n行,并將返回的行變成新的當前行。如果n或@nvar為負數(shù),返回游標尾之前的第n行,并將返回的行變成新的當前行。如果n或@nvar為0,則沒有行返回。 l RELATIVE {n | @nvar}:如果n或@nvar為正數(shù),返回當前行之后的第n行,并將返回的行變成新的當前行。如果n或@nvar為負數(shù),返回當前行之前的第n行,并將返回的行變成新的當前行。如果n或@nvar為0,返回當前行。如果對游標的第一次提取操作時將FETCHRELATIVE的n或@nvar指定為負數(shù)或0,則沒有行返回。n必須為整型常量且@nvar必須為smallint、tinyint或int。 說明:在前兩個參數(shù)中,包含了n和@nvar其表示游標相對與作為基準的數(shù)據(jù)行所偏離的位置。 l GLOBAL:指定cursor_name為全局游標。 l cursor_name:要從中進行提取的開放游標的名稱。如果同時有以cursor_name作為名稱的全局和局部游標存在,若指定為GLOBAL,則cursor_name對應(yīng)于全局游標,未指定GLOBAL,則對應(yīng)于局部游標。 l @cursor_variable_name:游標變量名,引用要進行提取操作的打開的游標。 l INTO @variable_name[,...n]:允許將提取操作的列數(shù)據(jù)放到局部變量中。列表中的各個變量從左到右與游標結(jié)果集中的相應(yīng)列相關(guān)聯(lián)。各變量的數(shù)據(jù)類型必須與相應(yīng)的結(jié)果列的數(shù)據(jù)類型匹配或是結(jié)果列數(shù)據(jù)類型所支持的隱性轉(zhuǎn)換。變量的數(shù)目必須與游標選擇列表中的列的數(shù)目一致。 l @@FETCH_STATUS:返回上次執(zhí)行FETCH命令的狀態(tài)。在每次用FETCH從游標中讀取數(shù)據(jù)時,都應(yīng)檢查該變量,以確定上次FETCH操作是否成功,決定如何進行下一步處理。@@FETCH_STATUS變量有3個不同的返回值,說明如下: 2 返回值為0:FETCH 語句成功。 2 返回值為-1:FETCH 語句失敗或此行不在結(jié)果集中。 2 返回值為-2:被提取的行不存在。 說明:當使用SQL-92語法來聲明一個游標時,沒有選擇SCROLL選項,則只能使用FETCH NEXT命令來從游標中讀取數(shù)據(jù),即只能從結(jié)果集第一行按順序地每次讀取一行。由于不能使用FIRST、LAST、PRIOR,所以無法回滾讀取以前的數(shù)據(jù)。如果選擇了SCROLL選項,則可以使用所有的FETCH操作。 通常游標取數(shù)的操作與WHILE循環(huán)緊密結(jié)合,下面將使用@@FETCH_STATUS控制在一個WHILE循環(huán)中的游標活動。 程序運行結(jié)果如圖1所示。
SQL語句如下: USE 銷售管理系統(tǒng) --引入數(shù)據(jù)庫 DECLARE ReadCursor CURSOR FOR --聲明一個游標 SELECT 操作員編號,操作員姓名,操作員性別,操作員住址 FROM 操作員信息表 OPEN ReadCursor --打開游標 FETCH NEXT FROM ReadCursor --執(zhí)行取數(shù)操作 WHILE @@FETCH_STATUS=0 --檢查@@FETCH_STATUS,以確定是否還可以繼續(xù)取數(shù) BEGIN FETCH NEXT FROM ReadCursor END 語法: CLOSE { { [ GLOBAL ] cursor_name } | cursor_variable_name } 參數(shù)說明: l GLOBAL:指定cursor_name為全局游標。 l cursor_name:開放游標的名稱。如果全局游標和局部游標都使用cursor_name作為它們的名稱,那么當指定GLOBAL時,cursor_name引用全局游標;否則,cursor_name引用局部游標。 l cursor_variable_name:與開放游標關(guān)聯(lián)的游標變量名稱。 示例: 聲明一個名為“CloseCursor”的游標,并使用Close語句關(guān)閉游標。 SQL語句如下: USE 銷售管理系統(tǒng) --引入數(shù)據(jù)庫 DECLARE CloseCursor Cursor FOR --聲明游標 SELECT * FROM 銷售表 FOR READ ON OPEN CloseCursor --打開游標 CLOSE CloseCursor --關(guān)閉游標 釋放游標 語法: DEALLOCATE { { [ GLOBAL ] cursor_name } | @cursor_variable_name } 參數(shù)說明: l cursor_name:已聲明游標的名稱。當全局和局部游標都以cursor_name作為它們的名稱存在時,如果指定GLOBAL,則cursor_name引用全局游標,如果未指定GLOBAL,則cursor_name引用局部游標。 l @cursor_variable_name:cursor變量的名稱。@cursor_variable_name必須為cursor類型。 當使用DEALLOCATE @cursor_variable_name來刪除游標時,游標變量并不會被釋放,除非超過使用該游標的存儲過程和觸發(fā)器的范圍。 示例: 使用DEALLOCATE命令釋放名為“FreeCursor”的游標。 SQL語句如下: USE 銷售管理系統(tǒng) DECLARE FreeCursor Cursor FOR --聲明游標 SELECT * FROM 銷售表 OPEN FreeCursor --打開游標 Close FreeCursor --關(guān)閉游標 DEALLOCATE FreeCursor --釋放游標 創(chuàng)建游標變量 首先創(chuàng)建一個游標并打開該游標,之后創(chuàng)建一個游標變量并將游標的值(SELECT * FROM Jobs)賦給游標變量,并通過FETCH語句讀取游標變量中的值,最后關(guān)閉并釋放游標。 程序運行結(jié)果如圖1所示。
SQL語句如下: USE pubs DECLARE MyCursor_001 Cursor FOR --創(chuàng)建游標 SELECT * FROM Jobs OPEN MyCursor_001 --打開游標DECLARE @CursorVar Cursor --創(chuàng)建游標變量 SET @CursorVar = MyCursor_001 --為游標變量賦值 FETCH NEXT FROM @CursorVar --讀取游標變量中的值 CLOSE MyCursor_001 --關(guān)閉游標 DEALLOCATE MyCursor_001 --釋放游標 靜態(tài)游標 對非鍵集列中的數(shù)據(jù)值所做的更改(由游標所有者更改或其他用戶提交)在用戶滾動游標時是可見的。在游標外對數(shù)據(jù)庫所做的插入在游標內(nèi)是不可見的,除非關(guān)閉并重新打開游標。 在查詢分析器中聲明變量,并設(shè)置@id變量的值,然后聲明一個游標并打開該游標,使用FETCH NEXT方法來獲取游標的下一行數(shù)據(jù),并將此數(shù)據(jù)賦值給變量,如果FETCH語句執(zhí)行成功則判斷當前游標所指定的操作員編號是否與變量@id相等,如果相等則更新數(shù)據(jù),最后關(guān)閉游標并釋放游標所占用的資源。 程序運行結(jié)果如圖1所示。 將編號為“CY20061010001”的操作員年齡修改為“30”歲 圖1 使用游標修改數(shù)據(jù) SQL語句如下: Declare @id char(20) /*聲明變量*/ declare @ids char(20) declare @names char(20) set @id='CY20061010001' --為變量賦值 DECLARE authors_cursor CURSOR --聲明游標 FOR SELECT 操作員編號,操作員姓名 FROM 操作員信息表 OPEN authors_cursor --打開游標 FETCH NEXT FROM authors_cursor --獲取游標的下一行數(shù)據(jù) into @ids,@names --使變量獲得當前游標指定行的操作員編號和操作員姓名 WHILE @@FETCH_STATUS = 0 --FETCH語句執(zhí)行成功 BEGIN if @id=@ids --判斷變量的值是否與游標指定的操作員編號相等 begin --更新指定條件的操作員年齡 update 操作員信息表 set 操作員年齡=30 where 操作員編號 = @ids end FETCH NEXT FROM authors_cursor --獲取游標的下一行 into @ids,@names --使變量獲得當前游標指定行的操作員編號和操作員姓名 End CLOSE authors_cursor --關(guān)閉游標 DEALLOCATE authors_cursor --釋放游標 SELECT * FROM 操作員信息表 --重新選擇操作員信息表 使用游標刪除數(shù)據(jù) 語法: Delete table_name SET column_name1-{expr [,column_name2={expr WHERE CURRENT OF cursor_name 參數(shù)說明: l table_name:用來指定UPDATE或DELETE的表名。 l column_name:用來指定UPDATE的列名。 l cursor_name:用來指定游標的名稱。 下面介紹如何使用WHERE CURRENT OF方法刪除數(shù)據(jù) 聲明一個游標并打開,然后使用FETCH NEXT方法將游標指針下移一行,最后使用WHERE CURRENT OF方法刪除指定條件的數(shù)據(jù),然后關(guān)閉并釋放游標所占用的系統(tǒng)資源。 SQL語句如下: USE 銷售管理系統(tǒng) --引入數(shù)據(jù)庫 DECLARE deletecursor CURSOR --聲明游標 FOR SELECT * FROM 操作員信息表 WHERE 操作員編號 = 'CY20061010211' OPEN deletecursor --打開游標 GO FETCH NEXT FROM deletecursor --游標指針下移一行 DELETE 操作員信息表 WHERE CURRENT OF deletecursor --刪除指定條件的數(shù)據(jù) FETCH NEXT FROM deletecursor GO CLOSE deletecursor --關(guān)閉游標 DEALLOCATE deletecursor --釋放游標 GO 下面介紹如何使用游標刪除數(shù)據(jù) 在查詢分析器中聲明變量,并設(shè)置@age變量的值,然后聲明一個游標并打開該游標,使用FETCH NEXT方法來獲取游標的下一行數(shù)據(jù),并將此數(shù)據(jù)賦值給變量,如果FETCH語句執(zhí)行成功,則判斷當前游標所指定的操作員年齡是否與變量@age相等,如果相等,則刪除此數(shù)據(jù),最后關(guān)閉游標并釋放游標所占用的系統(tǒng)資源。 SQL語句如下: USE 銷售管理系統(tǒng) --引入數(shù)據(jù)庫 DECLARE @id char(20) /*聲明變量*/ DECLARE @names char(20) DECLARE @age int SET @age = 30 --為變量賦值 DECLARE @ages int DECLARE deletecursor Cursor For --聲明游標 SELECT 操作員編號,操作員姓名,操作員年齡 FROM 操作員信息表 OPEN deletecursor --打開游標 FETCH NEXT FROM deletecursor --獲取游標的下一行 --使變量獲得當前游標指定行的操作員編號,操作員姓名,操作員年齡 into @id,@names,@ages WHILE @@FETCH_STATUS = 0 --FETCH語句執(zhí)行成功 BEGIN if @age = @ages --判斷變量的值是否與游標指定的操作員年齡相等 BEGIN --刪除指定條件的數(shù)據(jù) DELETE 操作員信息表 WHERE 操作員年齡 = @ages END FETCH NEXT FROM deletecursor --獲取游標的下一行 --使變量獲得當前游標指定行的操作員編號,操作員姓名,操作員年齡 into @id,@names,@ages END CLOSE deletecursor --關(guān)閉游標 DEALLOCATE deletecursor --釋放游標 將游標中的數(shù)據(jù)進行排序顯示 ORDERY BY子句語法: ORDER BY <column name> [ ASC | DESC ] [ ,...<last column name> [ ASC | DESC ]] 注意:與非游標的SELECT語句中的ORDER BY子句不同,只有在查詢的SELECT子句中列出的供顯示的列才能作為ORDER BY子句中的列出現(xiàn)(在非游標的SELECT語句中,表中任何在查詢的FROM子句中列出的列都可能出現(xiàn)在ORDER BY子句中,即使列沒有在SELECT子句中)。 下面將游標中的數(shù)據(jù)進行排序顯示 在聲明的mycursor游標中選擇指定的數(shù)據(jù)列,并將庫存數(shù)量進行降序顯示。 程序運行結(jié)果如圖1所示。 SQL語句如下: USE 銷售管理系統(tǒng) DECLARE mycursor CURSOR FOR SELECT 商品編號,商品名稱,庫存數(shù)量,庫存金額 FROM 庫存表 ORDER BY 庫存數(shù)量 DESC OPEN mycursor FETCH NEXT FROM mycursor WHILE @@FETCH_STATUS = 0 FETCH NEXT FROM mycursor CLOSE mycursor DEALLOCATE mycursor 使用FETCH語句將數(shù)據(jù)值存入變量 程序運行結(jié)果如圖1所示。
SQL語句如下: USE 銷售管理系統(tǒng) GO DECLARE @names char(20),@age char(20),@sex char(20) --聲明變量 DECLARE mycursor Cursor FOR --聲明游標 SELECT 操作員姓名,操作員年齡,操作員性別 FROM 操作員信息表 WHERE 操作員性別 = '男' ORDER BY 操作員編號 --按操作員編號進行排序 OPEN mycursor --打開游標 PRINT '操作員姓名 '+'操作員年齡 '+'操作員性別 ' --使用PRINT語句輸出字符串 FETCH NEXT FROM mycursor --游標指針下移一行 INTO @names,@age,@sex WHILE @@FETCH_STATUS = 0 --FETCH語句執(zhí)行成功 BEGIN PRINT + @names + @age + @sex --使用PRINT語句將數(shù)據(jù)輸出 FETCH NEXT FROM mycursor INTO @names,@age,@sex END CLOSE mycursor --關(guān)閉游標 DEALLOCATE mycursor --釋放游標 GO 在游標中包含計算列 聲明一個游標,在SELECT語句中選擇數(shù)據(jù)表中的某些數(shù)據(jù)字段,并將數(shù)量字段與金額字段中的數(shù)據(jù)進行相乘計算,然后通過FETCH NEXT語句每次向下移動游標指針,將當前指定的數(shù)據(jù)進行計算,最后關(guān)閉并釋放游標。 程序運行結(jié)果如圖1所示。
SQL語句如下: DECLARE cur CURSOR --聲明游標 FOR SELECT 商品編號,商品名稱,數(shù)量,金額, 數(shù)量*金額 as 銷售總額 FROM 銷售表 OPEN cur庫 --打開游標 FETCH NEXT FROM cur WHILE @@FETCH_STATUS = 0 --FETCH語句執(zhí)行成功 BEGIN FETCH NEXT FROM cur END CLOSE cur --關(guān)閉游標 DEALLOCATE cur --釋放游標 SELECT * FROM 銷售表 --選擇銷售表 |
|