SQL Server DML 語法(SELECT、UPDATE 和 DELETE)是以資料集為資料處理單位,方便且有效率,而 Cursor 則是以記錄為資料處理單位,對於資料操作彈性較大。
SQL Cursor 的基礎架構。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
DECLARE
curTemp
CURSOR
-- 宣告 Cursor 及其資料來源
FOR
(
SELECT
Col1,Col2,Col3......
FROM
SourceTable
WHERE
Condition
)
OPEN
curTemp
-- 打開 Cursor,並建立 Cursor 與資料表關連
DECLARE
@var1
as
.....
DECLARE
@var2
as
.....
FETCH
NEXT
FROM
curTemp
INTO
@var1,@var2
-- 將資料存進變數中
WHILE (@@FETCH_STATUS = 0)
-- 檢查是否有讀取到資料
BEGIN
....................
FETCH
NEXT
FROM
curTemp
INTO
@var1,@var2
END
CLOSE
curTemp
-- 關閉 Cursor,並關閉 Cursor 與資料表連結
DEALLOCATE
curTemp
-- 將 Cursor 物件移除
|
-
使用 Cursor 會導致 SQLServer 效能不彰,應視為最後手段,但假如使用時請注意下列事項:
- 盡量由前往後讀取資料就好 FORWARD_ONLY 和 FETCH NEXT 為預設值,不要使用 SCROLL 和 FETCH PRIOR、FETCH FIRST、FETCH LAST 等語法,個人習慣通常都會設定 FAST_FORWARD 來提高效率。
- 不要利用 Cursor 來修改和刪除資料,能明確指定為 READ_ONLY 較好。
判斷 Cursor 中的最後一筆資料利用 @@CURSOR_ROWS 來查詢最近一次 OPEN 的 Cursor 中有多少筆資料。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
DECLARE
@
Temp
Table
(EmpNO
char
(5),EmpName
nchar
(8))
INSERt
INTO
@
Temp
VALUES
(
'00001'
,
'張三'
)
INSERt
INTO
@
Temp
VALUES
(
'00002'
,
'李四'
)
INSERt
INTO
@
Temp
VALUES
(
'00003'
,
'王五'
)
-- Cursor 的 T-SQL 延伸語法
DECLARE
curTemp
CURSOR
STATIC
-- 宣告此 Cursor 為 STATIC
FOR
(
SELECT
EmpNO,EmpName
FROM
@
Temp
WHERE
EmpNO
IN
(
'00001'
,
'00002'
)
)
OPEN
curTemp
DECLARE
@EmpNO
as
char
(5),@EmpName
nchar
(8)
DECLARE
@
Count
as
smallint
SET
@
Count
= 0
-- 設定一個計數變數
FETCH
NEXT
FROM
curTemp
INTO
@EmpNO,@EmpName
WHILE (@@FETCH_STATUS = 0)
BEGIN
SET
@
Count
= @
Count
+ 1
IF @
Count
= @@CURSOR_ROWS
PRINT
'最後一筆資料為 '
+ @EmpName
FETCH
NEXT
FROM
curTemp
INTO
@EmpNO,@EmpName
END
CLOSE
curTemp
DEALLOCATE
curTemp
|
-
說明:
- 由於動態資料指標會反映所有變更,因此,Cursor 內資料列數會不斷改變,@@CURSOR_ROWS 永遠不可能明確指出 Cursor 內有多少資料列數,也因此必須把 Cursor 設為靜態指標(STATIC)。
- 宣告 Cursor 為 STATIC,會先把資料放進 TempDB 內,應盡量縮小資料量,以免 TempDB 瞬間爆增,影響效能。
-
MSDN 參考資料
- DECLARE CUROSR、FETCH、@@FETCH_STATUS 、@@CURSOR_ROWS
- 關於選擇資料指標類型