T-SQL游标学习总结
生活随笔
收集整理的這篇文章主要介紹了
T-SQL游标学习总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
T-SQL查詢進階-10分鐘理解游標
http://www.cnblogs.com/CareySon/archive/2011/11/01/2231381.html 概述在關系數據庫中,我們對于查詢的思考是面向集合的。而游標打破了這一規則,游標使得我們思考方式變為逐行進行.對于類C的開發人員來著,這樣的思考方式會更加舒服。
正常面向集合的思維方式是:
2
而對于游標來說:
3
這也是為什么游標是邪惡的,它會使開發人員變懶,懶得去想用面向集合的查詢方式實現某些功能. 同樣的,在性能上,游標會吃更多的內存,減少可用的并發,占用寬帶,鎖定資源,當然還有更多的代碼量…… 從游標對數據庫的讀取方式來說,不難看出游標為什么占用更多的資源,打個比方:
1
當你從ATM取錢的時候,是一次取1000效率更高呢,還是取10次100? 既然游標這么“邪惡”,為什么還要學習游標
我個人認為存在既是合理.歸結來說,學習游標原因我歸納為以下2點 1.現存系統有一些游標,我們查詢必須通過游標來實現 2.作為一個備用方式,當我們窮盡了while循環,子查詢,臨時表,表變量,自建函數或其他方式扔來無法實現某些查詢的時候,使用游標實現.
T-SQL中游標的生命周期以及實現 在T-SQL中,游標的生命周期由5部分組成
1.定義一個游標 在T-SQL中,定義一個游標可以是非常簡單,也可以相對復雜,取決于游標的參數.而游標的參數設置取決于你對游標原理的了解程度. 游標其實可以理解成一個定義在特定數據集上的指針,我們可以控制這個指針遍歷數據集,或者僅僅是指向特定的行,所以游標是定義在以Select開始的數據集上的:
4
T-SQL中的游標定義在MSDN中如下: DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ]? [ FORWARD_ONLY | SCROLL ]? [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]? [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]? [ TYPE_WARNING ]? FOR select_statement? [ FOR UPDATE [ OF column_name [ ,...n ] ] ] [;] 看起來很讓人頭痛是吧.下面仔細講一下如何定義游標: 游標分為游標類型和游標變量,對于游標變量來說,遵循T-SQL變量的定義方法(啥,不知道T-SQL變量定義的規則?參考我前面的博文).游標變量支持兩種方式賦值,定義時賦值和先定義后賦值,定義游標變量像定義其他局部變量一樣,在游標前加”@”,注意,如果定義全局的游標,只支持定義時直接賦值,并且不能在游標名稱前面加“@”,兩種定義方式如下:
5
下面我們來看游標定義的參數:
LOCAL和GLOBAL二選一 LOCAL意味著游標的生存周期只在批處理或函數或存儲過程中可見,而GLOBAL意味著游標對于特定連接作為上下文,全局內有效,例如:
6
如果不指定游標作用域,默認作用域為GLOBAL
FORWARD_ONLY 和 SCROLL 二選一
FORWARD_ONLY意味著游標只能從數據集開始向數據集結束的方向讀取,FETCH NEXT是唯一的選項,而SCROLL支持游標在定義的數據集中向任何方向,或任何位置移動,如下圖:
7
STATIC ?KEYSET ?DYNAMIC ?和 FAST_FORWARD 四選一 這四個關鍵字是游標所在數據集所反應的表內數據和游標讀取出的數據的關系 STATIC意味著,當游標被建立時,將會創建FOR后面的SELECT語句所包含數據集的副本存入tempdb數據庫中,任何對于底層表內數據的更改不會影響到游標的內容. DYNAMIC是和STATIC完全相反的選項,當底層數據庫更改時,游標的內容也隨之得到反映,在下一次fetch中,數據內容會隨之改變 KEYSET可以理解為介于STATIC和DYNAMIC的折中方案。將游標所在結果集的唯一能確定每一行的主鍵存入tempdb,當結果集中任何行改變或者刪除時,@@FETCH_STATUS會為-2,KEYSET無法探測新加入的數據
FAST_FORWARD可以理解成FORWARD_ONLY的優化版本.FORWARD_ONLY執行的是靜態計劃,而FAST_FORWARD是根據情況進行選擇采用動態計劃還是靜態計劃,大多數情況下FAST_FORWARD要比FORWARD_ONLY性能略好.
READ_ONLY ?SCROLL_LOCKS ?OPTIMISTIC 三選一? READ_ONLY意味著聲明的游標只能讀取數據,游標不能做任何更新操作
SCROLL_LOCKS是另一種極端,將讀入游標的所有數據進行鎖定,防止其他程序進行更改,以確保更新的絕對成功
OPTIMISTIC是相對比較好的一個選擇,OPTIMISTIC不鎖定任何數據,當需要在游標中更新數據時,如果底層表數據更新,則游標內數據更新不成功,如果,底層表數據未更新,則游標內表數據可以更新
2.打開游標
當定義完游標后,游標需要打開后使用,只有簡單一行代碼:
OPEN test_Cursor 注意,當全局游標和局部游標變量重名時,默認會打開局部變量游標
3.使用游標 游標的使用分為兩部分,一部分是操作游標在數據集內的指向,另一部分是將游標所指向的行的部分或全部內容進行操作 只有支持6種移動選項,分別為到第一行(FIRST),最后一行(LAST),下一行(NEXT),上一行(PRIOR),直接跳到某行(ABSOLUTE(n)),相對于目前跳幾行(RELATIVE(n)),例如:
8
對于未指定SCROLL選項的游標來說,只支持NEXT取值. 第一步操作完成后,就通過INTO關鍵字將這行的值傳入局部變量:
比如下面代碼:
10
9
游標經常會和全局變量@@FETCH_STATUS與WHILE循環來共同使用,以達到遍歷游標所在數據集的目的,例如:
11
4.關閉游標
在游標使用完之后,一定要記得關閉,只需要一行代碼:CLOSE+游標名稱
CLOSE test_Cursor 5.釋放游標
當游標不再需要被使用后,釋放游標,只需要一行代碼:DEALLOCATE+游標名稱
DEALLOCATE test_Cursor 對于游標一些優化建議
如果能不用游標,盡量不要使用游標 用完用完之后一定要關閉和釋放 盡量不要在大量數據上定義游標 盡量不要使用游標上更新數據 盡量不要使用insensitive, static和keyset這些參數定義游標 如果可以,盡量使用FAST_FORWARD關鍵字定義游標 如果只對數據進行讀取,當讀取時只用到FETCH NEXT選項,則最好使用FORWARD_ONLY參數 總結
本文從游標的基本概念,到生命周期來談游標。游標是非常邪惡的一種存在,使用游標經常會比使用面向集合的方法慢2-3倍,當游標定義在大數據量時,這個比例還會增加。如果可能,盡量使用while,子查詢,臨時表,函數,表變量等來替代游標,記住,游標永遠只是你最后無奈之下的選擇,而不是首選。 ========
T-SQL游標使用
http://blog.csdn.net/ht_927/article/details/6006778 ?使用游標(cursor) 的一個主要的原因就是把集合操作轉換成單個記錄處理方式。用 SQL 語言從數據庫中檢索數據后,結果放在內存的一塊區域中, 且結果往往是一個含有多個記錄的集合。游標機制允許用戶在 SQL server 內逐行地訪問這些記錄,按照用戶自己的意愿來顯示和處理這些記錄。 1. 為何使用游標: 使用游標 (cursor) 的一個主要的原因就是把集合操作轉換成單個記錄處理方式。用 SQL 語言從數據庫中檢索數據后,結果放在內存的一塊區域中,且結果往往是一個含有多個記錄的集合。游標機制允許用戶在 SQL server 內逐行地訪問這些記錄,按照用戶自己的意愿來顯示和處理這些記錄。 2. 如何使用游標: 一般地,使用游標都遵循下列的常規步驟: (1) ?聲明游標。把游標與 T-SQL 語句的結果集聯系起來。? (2) ?打開游標。? (3) ?使用游標操作數據。? (4) ?關閉游標。 2.1. 聲明游標 DECLARE CURSOR 語句 SQL-92 標準語法格式: DECLARE 游標名 [ INSENSITIVE ] [ SCROLL ] CURSOR FOR ? sql-statement Eg: Declare MycrsrVar Cursor FOR Select * FROM tbMyData 2.2 ?打開游標 OPEN MycrsrVar 當游標被打開時,行指針將指向該游標集第 1 行之前,如果要讀取游標集中的第 1 行數據,必須移動行指針使其指向第 1 行。就本例而言,可以使用下列操作讀取第 1 行數據: FETCH FIRST from E1cursor 或 FETCH NEXT from E1cursor 2.3 ? ? ?使用游標操作數據 ? ? 下面的示例用 @@FETCH_STATUS 控制在一個 WHILE 循環中的游標活動 /* 使用游標讀取數據的操作如下。 */ DECLARE E1cursor cursor /* 聲明游標,默認為 FORWARD_ONLY 游標 */ FOR SELECT * FROM c_example OPEN E1cursor /* 打開游標 */ FETCH NEXT from E1cursor /* 讀取第 1 行數據 */ WHILE @@FETCH_STATUS = 0 /* 用 WHILE 循環控制游標活動 */ BEGINFETCH NEXT from E1cursor /* 在循環體內將讀取其余行數據 */ END CLOSE E1cursor /* 關閉游標 */ DEALLOCATE E1cursor /* 刪除游標 */
2.4 ? ?關閉游標 使用CLOSE 語句關閉游標 CLOSE { { [ GLOBAL ]游標名 ?} | 游標變量名 ?} 使用DEALLOCATE 語句刪除游標,其語法格式如下: DEALLOCATE { { [ GLOBAL ]游標名 ?} | @ 游標變量名? 3. FETCH操作的簡明語法如下: FETCH [ NEXT | PRIOR | FIRST | LAST] FROM {游標名 ?| @ 游標變量名 ?} [ INTO @ 變量名 ?[ , …] ] 參數說明: NEXT ?取下一行的數據,并把下一行作為當前行 ( 遞增 ) 。由于打開游標后,行指針是指向該游標第 1 行之前,所以第一次執行 FETCH NEXT 操作將取得游標集中的第 1 行數據。 NEXT 為默認的游標提取選項。 INTO @變量名 [,…] ?把提取操作的列數據放到局部變量中。列表中的各個變量從左到右與游標結果集中的相應列相關聯。各變量的數據類型必須與相應的結果列的數據類型匹配或是結果列數據類型所支持的隱性轉換。變量的數目必須與游標選擇列表中的列的數目一致。 -------------------------------------------------------------------------------------------------------------------------------- 每執行一個FETCH 操作之后,通常都要查看一下全局變量 @@FETCH_STATUS 中的狀態值,以此判斷 FETCH 操作是否成功。該變量有三種狀態值: · 0 表示成功執行 FETCH 語句。 · -1 表示 FETCH 語句失敗,例如移動行指針使其超出了結果集。 · -2 表示被提取的行不存在。 由于@@FETCH_STATU 是全局變量,在一個連接上的所有游標都可能影響該變量的值。因此,在執行一條 FETCH 語句后,必須在對另一游標執行另一 FETCH 語句之前測試該變量的值才能作出正確的判斷。?
--示例? declare @Familyid int declare @address nvarchar(100) DECLARE E1cursor cursor /* 聲明游標,默認為 FORWARD_ONLY 游標 */ FOR SELECT address FROM FamilyInfo where Family_id<10 OPEN E1cursor /* 打開游標 */ FETCH NEXT from E1cursor into @address /* 讀取第 1 行數據 */ WHILE @@FETCH_STATUS = 0 /* 用 WHILE 循環控制游標活動 */ BEGIN SELECT * FROM mHUB_fnSplit(@address,'%') where @@rowcount<4 FETCH NEXT from E1cursor into @address /*讀取其它記錄 */ END CLOSE E1cursor DEALLOCATE E1cursor
========
SQL Server游標
http://www.cnblogs.com/knowledgesea/p/3699851.html 什么是游標 結果集,結果集就是select查詢之后返回的所有行數據的集合。游標則是處理結果集的一種機制吧,它可以定位到結果集中的某一行,多數據進行讀寫,也可以移動游標定位到你所需要的行中進行操作數據。
一般復雜的存儲過程,都會有游標的出現,他的用處主要有:
定位到結果集中的某一行。 對當前位置的數據進行讀寫。 可以對結果集中的數據單獨操作,而不是整行執行相同的操作。 是面向集合的數據庫管理系統和面向行的程序設計之間的橋梁。 游標的分類 根據游標檢測結果集變化的能力和消耗資源的情況不同,SQL Server支持的API服務器游標分為一下4種:
靜態游標: 靜態游標的結果集,在游標打開的時候建立在TempDB中,不論你在操作游標的時候,如何操作數據庫,游標中的數據集都不會變。例如你在游標打開的時候,對游標查詢的數據表數據進行增刪改,操作之后,靜態游標中select的數據依舊顯示的為沒有操作之前的數據。如果想與操作之后的數據一致,則重新關閉打開游標即可。 動態游標:這個則與靜態游標相對,滾動游標時,動態游標反應結果集中的所有更改。結果集中的行數據值、順序和成員在每次提取時都會變化。所有用戶做的增刪改語句通過游標均可見。如果使用API函數或T-SQL Where Current of子句通過游標進行更新,他們將立即可見。在游標外部所做的更新直到提交時才可見。 只進游標:只進游標不支持滾動,只支持從頭到尾順序提取數據,數據庫執行增刪改,在提取時是可見的,但由于該游標只能進不能向后滾動,所以在行提取后對行做增刪改是不可見的。 鍵集驅動游標:打開鍵集驅動游標時,該有表中的各個成員身份和順序是固定的。打開游標時,結果集這些行數據被一組唯一標識符標識,被標識的列做刪改時,用戶滾動游標是可見的,如果沒被標識的列增該,則不可見,比如insert一條數據,是不可見的,若可見,須關閉重新打開游標。 靜態游標在滾動時檢測不到表數據變化,但消耗的資源相對很少。動態游標在滾動時能檢測到所有表數據變化,但消耗的資源卻較多。鍵集驅動游標則處于他們中間,所以根據需求建立適合自己的游標,避免資源浪費。。
游標的生命周期 游標的生命周期包含有五個階段:聲明游標、打開游標、讀取游標數據、關閉游標、釋放游標。
1.聲明游標,語法
復制代碼 DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ]? [ FORWARD_ONLY | SCROLL ]? [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]? [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]? [ TYPE_WARNING ]? FOR select_statement? [ FOR UPDATE [ OF column_name [ ,...n ] ] ]
復制代碼 參數說明:
cursor_name:游標名稱。 Local:作用域為局部,只在定義它的批處理,存儲過程或觸發器中有效。 Global:作用域為全局,由連接執行的任何存儲過程或批處理中,都可以引用該游標。 [Local | Global]:默認為local。 Forward_Only:指定游標智能從第一行滾到最后一行。Fetch Next是唯一支持的提取選項。如果在指定Forward_Only是不指定Static、KeySet、Dynamic關鍵字,默認為Dynamic游標。如果Forward_Only和Scroll沒有指定,Static、KeySet、Dynamic游標默認為Scroll,Fast_Forward默認為Forward_Only Static:靜態游標 KeySet:鍵集游標 Dynamic:動態游標,不支持Absolute提取選項 Fast_Forward:指定啟用了性能優化的Forward_Only、Read_Only游標。如果指定啦Scroll或For_Update,就不能指定他啦。 Read_Only:不能通過游標對數據進行刪改。 Scroll_Locks:將行讀入游標是,鎖定這些行,確保刪除或更新一定會成功。如果指定啦Fast_Forward或Static,就不能指定他啦。 Optimistic:指定如果行自讀入游標以來已得到更新,則通過游標進行的定位更新或定位刪除不成功。當將行讀入游標時,sqlserver不鎖定行,它改用timestamp列值的比較結果來確定行讀入游標后是否發生了修改,如果表不行timestamp列,它改用校驗和值進行確定。如果已修改改行,則嘗試進行的定位更新或刪除將失敗。如果指定啦Fast_Forward,則不能指定他。 Type_Warning:指定將游標從所請求的類型隱式轉換為另一種類型時向客戶端發送警告信息。 For Update[of column_name ,....] :定義游標中可更新的列。 2.聲明一個動態游標
declare orderNum_02_cursor cursor scroll for select OrderId from bigorder where orderNum='ZEORD003402' 3.打開游標
--打開游標語法 open [ Global ] cursor_name | cursor_variable_name cursor_name:游標名,cursor_variable_name:游標變量名稱,該變量引用了一個游標。
--打開游標 open orderNum_02_cursor 4.提取數據
復制代碼 --提取游標語法 Fetch [ [Next|prior|Frist|Last|Absoute n|Relative n ] from ] [Global] cursor_name [into @variable_name[,....]] 復制代碼 參數說明:
Frist:結果集的第一行 Prior:當前位置的上一行 Next:當前位置的下一行 Last:最后一行 Absoute n:從游標的第一行開始數,第n行。 Relative n:從當前位置數,第n行。 Into @variable_name[,...] : 將提取到的數據存放到變量variable_name中。 例子:
復制代碼 --提取數據 fetch first from orderNum_02_cursor fetch relative 3 from orderNum_02_cursor fetch next from orderNum_02_cursor fetch absolute 4 from orderNum_02_cursor fetch next from orderNum_02_cursor fetch last from orderNum_02_cursor? fetch prior from orderNum_02_cursor select * from bigorder where orderNum='ZEORD003402' 復制代碼 結果(對比一下,就明白啦):
例子:
--提取數據賦值給變量 declare @OrderId int fetch absolute 3 from orderNum_02_cursor into @OrderId select @OrderId as id select * from bigorder where orderNum='ZEORD003402' 結果:
通過檢測全局變量@@Fetch_Status的值,獲得提取狀態信息,該狀態用于判斷Fetch語句返回數據的有效性。當執行一條Fetch語句之后,@@Fetch_Status可能出現3種值:0,Fetch語句成功。-1:Fetch語句失敗或行不在結果集中。-2:提取的行不存在。
這個狀態值可以幫你判斷提取數據的成功與否。
復制代碼 declare @OrderId int fetch absolute 3 from orderNum_02_cursor into @OrderId while @@fetch_status=0 ?--提取成功,進行下一條數據的提取操作 begin select @OrderId as id fetch ?next from orderNum_02_cursor into @OrderId ?--移動游標 end? 復制代碼 5.利用游標更新刪除數據?
--游標修改當前數據語法 Update 基表名 Set 列名=值[,...] Where Current of 游標名 --游標刪除當前數據語法 Delete 基表名 ?Where Current of 游標名 復制代碼 ---游標更新刪除當前數據 ---1.聲明游標 declare orderNum_03_cursor cursor scroll for select OrderId ,userId from bigorder where orderNum='ZEORD003402' --2.打開游標 open orderNum_03_cursor --3.聲明游標提取數據所要存放的變量 declare @OrderId int ,@userId varchar(15) --4.定位游標到哪一行 fetch First from orderNum_03_cursor into @OrderId,@userId --into的變量數量必須與游標查詢結果集的列數相同 while @@fetch_status=0 --提取成功,進行下一條數據的提取操作 beginif @OrderId=122182beginUpdate bigorder Set UserId='123' Where Current of orderNum_03_cursor --修改當前行endif @OrderId=154074beginDelete bigorder Where Current of orderNum_03_cursor --刪除當前行endfetch next from orderNum_03_cursor into @OrderId ,@userId --移動游標end
6.關閉游標
游標打開后,服務器會專門為游標分配一定的內存空間存放游標操作的數據結果集,同時使用游標也會對某些數據進行封鎖。所以游標一旦用過,應及時關閉,避免服務器資源浪費。
--關閉游標語法 close [ Global ] cursor_name | cursor_variable_name --關閉游標 close orderNum_03_cursor 7.刪除游標
刪除游標,釋放資源
--釋放游標語法 deallocate ?[ Global ] cursor_name | cursor_variable_name --釋放游標 deallocate orderNum_03_cursor ========
T-SQL 游標 游標更新數據
http://blog.sina.com.cn/s/blog_56294d0a0101fj77.html 游標的引入 1 .在數據的開發過程中,從某一結果集中逐一讀取一條記錄,用游標解決,游標占資源大,確定不用后將其釋放。 2 .聲明游標(四個組成部分) ( 1 ).declare游標 ( 2 ).open游標 ( 3 ).從一個游標中fetch信息 ( 4 ).close或deallocate游標 一、聲明游標主要內容: ( 1 ).游標名字 ( 2 ).數據來源表和列 ( 3 ).選取條件 ( 4 ).屬性僅讀或可修改 1 .語法格式: declare ?游標名稱 ?[ scroll ] ? cursor? [ local|global ]? [ forward_only|scroll ]? for ?選擇語句 [ for[read_only|update [of 字段名稱1,字段名稱2, ] ]] 其中: 1 > .local | global指定該游標的作用域是局部的還是全局的。 2 > .如果把forward_only選擇為forward_only, 則游標只能從第一行滾動到最后一行。 3 > .scroll表明所有的提取操作,如first,last,prior, next ,relative,absolute都可用。如不使用該保留字,那么只能進行next提取操作。 4 > .選擇語句:是定義結果集的select語句,應該注意的是在游標中不能使用compute, compute ? by ? for ?browse ?into語句. 5 > . read ? only :表明不允許游標內的數據被更新。 6 > . update [ of 字段名1[, n ] ]:定義在游標中可被修改的列。 例1:標準游標 declare taihang cursor for select id,name,address,city,statefrom table例2:只讀游標 declare taihang cursor for select id,name,address,city,atatefrom table for read only
例3:更新游標 declare taihang cursor for select name,addressfrom table for update
? 二、打開游標 1 .聲明之后,如要從游標中讀取數據,必須打開游標,使用open命令。 語法: open 游標名稱 注意: 1 > .在打開游標時,如果游標聲明語句中使用了insensitive保留字,則open產生一個臨時表來存放結果集。如果在結果集中任何一行數據的大小超過SQL Server定義的最大行尺寸時,open命令將失敗。 2 > .insensitive: 表明SQL Server會將游標定義所選取出來的數據記錄存放在一臨時表內,(建立在tempdb數據庫下)對該游標的操作皆由臨時表來應答。因此,對 基本表的修改并不影響游標提取數據,即游標不會隨著基本表內容的改變面改變,同時也不法通過游標來更新基本表。 如果不使用該保留字,那么對基本表的更新,刪除都會公映到游標中。 三、讀取游標中的數據- fetch? 1 .當游標被成功打開以后就可以從游標中逐行地讀取數據以時行相關處理。從游標中讀取數據主要使用fetch命令。 語法: fetch? [ [next|prior|first|last |absolute{n|@nvar} |relative{n|@nvar} ]? from ] cursor_name [ into @variable_name1,@variable_name2 ]? 注: 1 > . next :返回結果集中當前行的下一行,并增加當前行數為返回行行數。如果fetch next是第一次讀取游標中數據,則返回結果集中的第一行而不是第二行。 2 > .prior:返回結果集中當前行的前一行,并減少當前行數為返回行行數。如果fetch prior是第一次讀取游標中的數據,剛無數據記錄返回,并把游標位置設為第一行。 3 > .first:返回游標中的第一行。 4 > .last:返回游標中的最后一行。 5 > .absolute{n | @nvar }:如果N或 @nvar為正數 ,則表示從游標中返回的數據行數。如果N或 @nvar為負數,則返回游標內從最后一行數據算起的第N或 @nvar行數據 。若N或 @nvar超過游標的數據子集范疇 ,則@@fetch_status返回 - 1 。在該情況下,如果N或 @nvar為負數 ,則再執行fetch next命令會得到第一行數據;如果N或 @nvar為正值 ,如執行fetch prior命令剛會得到最后一行數據。N或 @nvar可以是固定值 ,也可以是smallint,tinyint或int類型的變量。 6 > .relative{N | @nvar }:若N或 @nvar為正數 ,則讀取游標當前位置起向后的第N或 @nvar行數據 。如果N或@nvar為負數 ,則返回游標當前位置起向前的第N或 @nvar行數據 。若N或 @nvar超過游標的數據子集范疇 ,則 @@fetch_status返回 - 1 。在該情況下,如果N或 @nvar為負數 ,則再執行fetch next命令會得到第一行數據;如果N或 @nvar為正值 ,如執行fetch prior命令剛會得到最后一行數據。N或 @nvar可以是固定值 ,也可以是smallint,tinyint或int類型的變量。 7 > . into @variable_name [ , n ] :允許使用fetch命令讀取的數據存放在多個變量中;在變量行中的每個變量必須與游標結果集中相應的列相對應,每一變量的數據類型也要與游標中的數據列的數據類型相匹配。 2 .檢查游標狀態 @@fetch_status :全局變量,返回上次執行fetch命令的狀態,在每次用fetch從游標中讀取數據時,都應檢查該變量以確定上次fetch操作是否成功,來決定如何進行下一步處理。 @@fetch_status變量有三個不同返回值。 1 > . 0 :表示成功取出了一行。 2 > . - 1表示未取到數據。游標位置超出結果集。 3 > . - 2表示返回的行已經不再是結果集的一個成員,這種情況只有在游標不是insensitive的情況下出現,即其它進程已刪除了行或改變了游標打開的關鍵值。 3 .編輯當前游標行 通 常,用游標來從基礎表中檢索數據,以實現對數據行處理,在修改游標中的數據,即進行定位更新或刪除游標所包含的數據,所以必須執行另外的更新或刪除命令, 并在where子句中重新給定條件才能修改到該行數據,但是如果在聲明游標時使用了for update語句那么就可以在update或delete命令 中以where ?current ?of關鍵字直接修改或刪除當前游標中所存儲的數據,而不必使用where子句重新給出指定條件。當改變游標中數據時,這種變化會自動地影響到游標的基礎表。但是如果在聲明游標時選擇了insensitive選項時,該游標中的數據不能被修改。 進行定位修改或刪除游標中的數據的語法規則語法: update ?table_name set ?column_name1 = {expression1 | null (select_statement)} [ ,column_name2={expression2|null(select_statement)} ]? where ? current ? of ?cursor_name delete ? from ?table_name where ? current ? of ?cursor_name 其中: 1 > .table_name:是update或delete的表名。 2 > .column_name:uqdate的列名 3 > .cursor_name:游標名 例1:首先聲明一個游標 declare authors_cur scroll cursor for select * from authorsfor update of au_lname,au_fname 更新authors表中的au_lname和au_fname列 update authorsset au_lname = ' china ' ,au_fname = ' asia ' where current of authors_cur 刪除authors表中的一行數據 delete ? from ?authors where ? current ? of ?authors_cur 注:以上的更新或刪除操作總是在游標的當前位置, 例:下面是一個完整的定位更新的例子。 declare @au_id int ( 11 ), @au_lname varchar ( 40 ), @au_fname varchar ( 20 )declare authors_cur cursor for select au_id,au_lname,au_fname from authorsfor update of au_id,aulname,au_fnameopen authors_cur fetch next from authors_cer into @au_id , @au_lname , @au_fname while @@fetch_status = 0 begin if @au_id = ' 172-32-1176 ' update authorsset au_lname = ' smith ' ,au_fname = ' jake ' where current of authors_curfetch next from authors_cer into @au_id , @au_lname , @au_fname end deallocate authors_cur
四、釋放游標 1 .關閉游標 使用close命令關閉游標,在處理完游標中數據之后,發布關閉游標來釋放數據結果集和定位于數據記錄上的鎖,close語句關閉游標但不釋放游標占用的數據結構。如果準備在隨后的使用中再次打開游標,則應使用open命令。 語法: close ?游標名稱 2 .釋放游標 在使用游標時各種針對游標的操作或者引用游標各或者引用指向游標的游標變量,當close命令關閉游標時并沒有釋放游標占用的數據結構。因此常使用deallocate命令刪除掉游標與游標名或游標變量之間的聯系,并且釋放游標占用的所有系統資源。 語法: deallocate ?游標名稱 ========
請問怎么用T-sql實現游標的遞歸
好象TSQL里面游標是個全局變量 有沒有其他方法可以解決啊
可以借助存儲過程的遞歸,在存儲過程內部使用LOCAL聲明游標為局部游標。
create ? ? FUNCTION ? dbo.GetSubClass(@Code_No ? varchar(50),@IdStr ? varchar(8000)='',@LevelCount ? int=-1) ? ?? /* ?? 參數: @Code_No ? ,被搜索子類的ID ?? @IdStr,一個特殊參數,用于在遞歸中傳數據,注意:調用函數時一定要傳入‘’空值 ?? @LevelCount ? 用于判斷是不是遞歸調用的最上層 ?? */ ?? RETURNS ? Varchar(8000) ?? AS ? ? ?? BEGIN ? ?? Declare ? @single_no ? varchar(50), ? @TC_ID ? varchar(50),@TC_PID ? Varchar(50),@StartLevel ? int,@Id32 ? int,@Ma_price ? Numeric(19,3) ?? if ? @LevelCount=-1 ?? begin ?? set ? @StartLevel=@@NESTLEVEL ?? set ? @LevelCount=@StartLevel ?? end ?? else ? ?? set ? @StartLevel=-1 ?? If ? @IdStr='' ? Set ?? @IdStr=''''+@InputId ? +'''' ?? DECLARE ? TreeClass ? CURSOR ? local ? FOR ? --定義游標 ?? Select ? b.single_no,b.Code_No ? From ? Mrp_Modec ? a ? ,Mrp_Mode ? b ? where ? a.single_no=b.single_no ? and ? In_Code= ? @InputId ?? OPEN ? TreeClass ?? FETCH ? NEXT ? FROM ? TreeClass ?? INTO ? @single_no,@TC_ID ?? WHILE ? @@FETCH_STATUS ? = ? 0 --循環游標,即循環當前類的弟一級子類 ?? BEGIN ?? if ? ? ? ? exists(select ? * ? from ? mrp_modec ? ? ) ? ?? select ? @Ma_price=Sum(sta_qty*u_price) ? from ? ? ? Mrp_Modec ? Where ? ? ? single_no=@single_no ? ? ?? update ? 表名 ? SET ? 字段= ? @Ma_price ? WHERE ? ? ? single_no=@single_no ? ? --這里為什么通不過 ?? select ? @IdStr= ? @IdStr+','+cast(@tC_ID ? as ? varchar)+'''' ?? if ? @@NESTLEVEL<32 ?? set ? @IdStr= ? dbo.GetSubClass(@TC_ID,@IdStr,@LevelCount) ? --遞歸。 ?? else ?? set ? @IdStr='['+cast(@tC_ID ? as ? varchar)+']'+@IdStr ?? FETCH ? NEXT ? FROM ? TreeClass ? iNTO ? @single_no,@tC_ID ? ?? End ?? CLOSE ? TreeClass ?? DEALLOCATE ? TreeClass ?? /*while ? @StartLevel=@@NESTLEVEL ? and ? charindex(']',@IdStr)>0 ?? begin ?? set ? @Id32=substring(@IdStr,2,charindex(']',@IdStr)-2) ?? set ? @IdStr=dbo.FN_32GetSubClass ? (@Id32,@IdStr,@LevelCount) ?? set ? @IdStr=replace(@IdStr,'['+cast(@Id32 ? as ? varchar)+']','') ?? end ?? */ ?? Return ? ? @IdStr ?? END ?? 但是我還要輸出游標啊? 得到一個結果集 對這個結果集在操作 其中要用到遞歸
樓主參考一下: http://community.csdn.net/Expert/topic/4896/4896332.xml?temp=.569317
游標默認定義是global
用下面的定義就可以了
declare 游標名 CURSOR LOCAL ?-- LOCAL指定游標為局部的(默認是GLOBAL, 全局的) FOR
但是遞歸怎么辦啊? 輸出參數為游標 ========
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的T-SQL游标学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS调试js学习总结
- 下一篇: Win32 API 和 ODBC 访问数