1. 程式人生 > >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 迴圈控制遊標活動 */
BEGIN
         FETCH 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  --提取成功,進行下一條資料的提取操作 
 begin
   if @OrderId=122182
     begin
     Update bigorder Set UserId='123' Where Current of  orderNum_03_cursor  --修改當前行
     end
   if @OrderId=154074
      begin
      Delete bigorder Where Current of  orderNum_03_cursor  --刪除當前行
      end
   fetch 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,state
 from   table 

 例2:只讀遊標
 declare  taihang  cursor 
 for 
 select  id,name,address,city,atate
 from   table 
 for   read   only 

 例3:更新遊標
 declare  taihang  cursor 
 for 
 select  name,address
 from   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  authors
 for   update   of  au_lname,au_fname
 更新authors表中的au_lname和au_fname列  
update  authors
 set  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  authors
 for   update   of  au_id,aulname,au_fname
 open  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  authors
 set  au_lname = ' smith ' ,au_fname = ' jake ' 
 where   current   of  authors_cur
  
 fetch   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   @[email protected]@NESTLEVEL      set   @[email protected]      end      else        set   @StartLevel=-1      If   @IdStr=''   Set              @IdStr=''''[email protected]   +''''      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       [email protected]_no                            update   表名   SET   欄位=   @Ma_price   WHERE       [email protected]_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)+']'[email protected]      FETCH   NEXT   FROM   TreeClass   iNTO   @single_no,@tC_ID        End      CLOSE   TreeClass      DEALLOCATE   TreeClass      /*while   @[email protected]@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 但是遞迴怎麼辦啊  輸出引數為遊標 ========

相關推薦

T-SQL遊標學習總結

T-SQL查詢進階-10分鐘理解遊標 http://www.cnblogs.com/CareySon/archive/2011/11/01/2231381.html 概述        在關係資料庫中,我們對於查詢的思考是面向集合的。而遊標打破了這一規則,遊標使得我們思考

SQL資料庫學習總結

經過一段時間的學習,也對資料庫有了一些認識,資料庫基本是由表,關係,操作組成;對於初學者首先要學的 經過一段時間的學習,也對資料庫有了一些認識。   資料庫基本是由表,關係,操作組成;對於初學者首先要學的:    1.資料庫是如何儲存資料的     表,約束,觸發器

SQL Server學習總結--初級

use School --插入teacher所有欄位的資料.如果在表後沒有指定需要插入的欄位名稱,那麼就預設為所有欄位新增值 --但是一定需要注意的是:標識列永遠不能自定義值--不能人為插入值 --僅當使用了列列表並且 IDENTITY_INSERT 為 ON 時,才能為表'Teacher'中的標識列指定顯

sql中關於T-sql遊標的使用(附有例項)

select *from Student order by SName for read only open s_sur select @@CURSOR_ROWS fetch next from s_sur update Student set SAge ='50' where current of s_su

SQL server學習(五)——T-SQL編程之存儲過程

mds ren creat 存儲 創建數據庫 希望 with 接收 bank 周五了,祝大家周末愉快。 之前一直在寫SQL server的分享,今天再來個T-SQL編程中的存儲過程。 存儲過程 存儲過程(procedure)類似於C語言中的函數,用來執行管理任務或應用復雜的

5月11日 python學習總結 子查詢、pymysql模塊增刪改查、防止sql註入問題

hal port 註入 any dict lex absolut username 參數 一、子查詢    子查詢:把一個查詢語句用括號括起來,當做另外一條查詢語句的條件去用,稱為子查詢 select emp.name from emp inner join dep on

學習筆記之T-SQL插入數據INSERT語法和數據庫編程實戰技巧[圖]

INSERT 數據庫 IT 編程 學習 一直以來就有寫博客的習慣,記錄一下學習心得、生活點滴等等,感覺也蠻好的,去年開始萌生了建立一個讀書和文學博客的想法,於是就開始實施了,中途也遇到不少難題,不過還好,都逐漸解決了,雖然我在技術方面有欠缺,但好在有同學們幫忙。 今天想和大家分享的學習筆記

【SqlServer】SqlServer編程語言T-SQL遊標使用

cal 而不是 失敗 指定 pdb 連接 last keyset 管理系 什麽是遊標 結果集,結果集就是select查詢之後返回的所有行數據的集合。 遊標則是處理結果集的一種機制吧,它可以定位到結果集中的某一行,多數據進行讀寫,也可以移動遊標定位到你所需要的行中進行操作

SQL註入學習總結(八):其他SQL註入的異或註入

href http 發現 .sql 異或 ascii 3.2 運算 證明 其他類型註入的詳解(5) 5.sql異或註入 背景當我們在嘗試SQL註入時,發現union,and被完全過濾掉了,就可以考慮使用異或註入 知識點 異或運算規則: 1^1=0 0^0=0 0^1=1 1

資料庫視訊總結(四)——T-sql語句

T-sql語句 分類: 1、 資料定義語言 2、 資料操縱語言 3、資料控制語言 其他常用型別: 1、事務管理語言 2、流程控制語言 3、附加的語言元素 常量與變數: 何如宣告變數 語法格式: DECLARE {@名稱 as 型別 |@ 給變數賦值可以使用S

SQL Server Log Shipping學習總結

  SQL Server的日誌傳送(log shipping)技術一直比較雞肋,尤其當SQL Server 推出了Always On技術以後,估計使用日誌傳送(log shipping)這種技術方案的企業越來越少,但是日誌傳送也有自己的一些優點,有些特殊場景或業務背景下也有其存在的價值。最近由於特

Linq to Sql學習總結3

儲存過程: 關係資料庫中的儲存過程在實體類中對映為具體的方法,直接將儲存過程拖動到對應的dbml設計檢視中即可,如圖: 在將儲存過程拖入dbml設計檢視中時,系統執行了如下命令: SET FMTONLY ON;--表示只獲取結果集的元資料(即相關列名 ) exec sp_Name SET

Linq to Sql學習總結4

延遲執行: Linq to sql 查詢句法在定義時並不會執行,只有在呼叫的時候才會執行(執行T_Sql查詢),每呼叫一次就會執行一次。對於需要多次呼叫的情況,可以使用ToList()方法先把結果集儲存下來。 DataLoadOptions DataLoadOptions options = ne

Linq to Sql學習總結5

修改併發異常ChangeConfictException //測試修改併發異常ChangeConfictException var query = from p in ctx.Products where p.Category

Linq to Sql學習總結6

單表繼承 繼承實體定義: //linq to sql支援實體單表繼承,即某一實體類(具有對映關係的類)可以派生多個子類,子類不用再通過特性對映基類的關係資料 //子類對基類實體進行分類,通過特性InheritanceMapping對基類實體分類 //基類實體以某一成員屬性作

T-SQL學習的筆記,以備查閱

create database MyDatabseOne; --建立資料庫 drop database MydatabaseOne; --刪除資料庫; --如果直接點"執行"將是執行所有語句,而選中某些則是單獨執行 --以下程式碼建立資料庫的初始值 create database Mydatabase

MyBatis學習總結(六)---使用log4j2將sql語句執行記錄輸出控制檯和檔案中

  在上一篇部落格中我簡單的介紹了在MyBatis中如何使用日誌,並給出了一個在MyBatis中使用log4j的示例。    MyBatis中日誌的使用及使用log4j示例   下面介紹在MyBatis中如何使用log4j2將sql語句執行記錄輸出控制

SQL Server學習筆記-T-SQL基本語句

T-SQL基本語句 基本的SELECT語句 Select語句的基本語法規則 SELECT [ALL|DISTINCT] [TOP (<expression>) [PERCENT] [WITH TIES]] FROM <source table(s)/view(s)>] [WH

Mybatis學習總結三之簡化sql對映xml檔案中的引用及解決欄位名與實體類屬性名不相同的衝突

一、為實體類定義別名,簡化sql對映xml檔案中的引用 我們在sql對映xml檔案中的引用實體類時,需要寫上實體類的全類名(包名+類名),如下:parameterType="com.aiit.pojo.User"這裡寫的實體類User的全類名com.aiit.pojo.User, <i

pl/sql使用心得,學習總結

設定 常用設定及快捷鍵 https://blog.csdn.net/wildboy2001/article/details/6887792 輸入中文跳出建表框的問題 檢查發現時快捷鍵配置中建表的快捷鍵為空導致的,給建表設定一個快捷鍵就好了 怎麼將介面中文化 https