# MsSql Cursor應用 ###### tags: `MSSQL` , `連猴子也能懂系列` >參考文件:https://docs.microsoft.com/zh-tw/sql/t-sql/language-elements/declare-cursor-transact-sql?view=sql-server-ver15 1.語法 === DECLARE CURSOR 子句 ```sql= 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 ] ] ] ``` --- 2.引數 === 2.1 游標有效範圍:**LOCAL** | GLOBAL * LOCAL:區域游標表示該游標只在這個範圍內有效。 * GLOBAL:全域游標表示該游標可以在同一個 connection 下的所有 sp 或 batch 中共用。 2.2 游標讀取方式:**FORWARD_ONLY** | SCROLL * **FORWARD_ONLY**:游標只可以順向讀取( FETCH NEXT )。 * SCROLL:這個項選表示可以使用所有 FETCH 功能: -FETCH FIRST:位置跳到 第一筆 -FETCH LAST:位置跳到 最後一筆 -**FETCH NEXT**:位置跳到 下一筆 -FETCH PRIOR:位置跳到 上一筆 -FETCH ABSOLUTE n:位置跳到 第n行 -FETCH RELATIVE n:當前位置開始的第n行 2.3 游標型態:STATIC | KEYSET | DYNAMIC | **FAST_FORWARD** * STATIC:靜態資料指標,唯讀,且無法得知其他使用者的變更。 * KEYSET:索引鍵集資料指標,使用索引值關連到來源資料表中的實際資料。 * DYNAMIC:動態資料指標。 * **FAST_FORWARD**:效能最佳化,這種資料指標類型不允許從資料指標內部修改資料。使用 FAST_FORWARD 等同使用 FORWARD_ONLY + READ_ONLY 2.4 Concurrency Options * READ_ONLY:唯讀游標,不鎖定。 * SCROLL_LOCKS:當資料列讀入資料游標時,SQL Server 會立即鎖定這些資料列,以確保之後可對它們進行修改。 * OPTIMISTIC:不鎖定。原始資料中之記錄若已被異動,再由Cursor去異動該筆記錄時會導致失敗。 --- 3.提取狀態 - @@FETCH_STATUS === * 0: 提取成功 * -1: 提取失敗 * -2: 要獲取之記錄已不存在 --- 4.建議用法 === Carey大大建議使用==FAST_FORWARD==,避免影響效能 大致流程: ```flow st=>start: 開始 e=>end: 結束 op1=>operation: 將table資料寫入Cursor op2=>operation: cond1=>condition: 迴圈(抓值成功) Fetch == 0 ? s1=>subroutine: Do something s2=>subroutine: Fetch next from Cursor st->op1->cond1 cond1(yes, right)->s1->s2(right)->cond1 cond1(no, left)->e ``` 範例: ```sql= --宣告游標需要用到的參數 DECLARE @TableName VARCHAR(128) --table 名稱 --建立Cursor, 取得需要Switch Table 清單 DECLARE TableCursor CURSOR LOCAL FAST_FORWARD FOR SELECT TableName FROM MoveToHistoryTableName --迴圈執行每一筆 OPEN TableCursor FETCH NEXT FROM TableCursor INTO @TableName; --擷取游標內容 WHILE @@FETCH_STATUS = 0 BEGIN PRINT 'table name: ' + @TableName; --印出表名稱 --(do something) --next FETCH NEXT FROM TableCursor INTO @TableName; END; --close cursor CLOSE TableCursor; DEALLOCATE TableCursor; ```