MS SQL Server 遊標

1. 定義遊標定義
遊標語句的核心是定義了一個遊標標識名,並把遊標標識名和一個查詢語句關聯起來。DECLARE語句用於聲明遊標,它通過SELECT查詢定義遊標存儲的數據集合。語句格式爲:
DECLARE 遊標名稱 [INSENSITIVE] [SCROLL]
CURSOR FOR select語句
[FOR{READ ONLY|UPDATE[OF 列名字表]}]
參數說明:
INSENSITIVE選項:說明所定義的遊標使用SELECT語句查詢結果的拷貝,對遊標的操作都基於該拷貝進行。因此,這期間對遊標基本表的數據修改不能反映到遊標中。這種遊標也不允許通過它修改基本表的數據。
SCROLL選項:指定該遊標可用所有的遊標數據定位方法提取數據,遊標定位方法包括PRIOR、FIRST、LAST、ABSOLUTE n 和RELATIVE n 選項。
Select語句:爲標準的SELECT查詢語句,其查詢結果爲遊標的數據集合,構成遊標數據集合的一個或多個表稱作遊標的基表。
在遊標聲明語句中,有下列條件之一時,系統自動把遊標定義爲INSENSITIVE遊標:
SELECT語句中使用了DISTINCT、UNION、 GROUP BY或HAVING等關鍵字;
任一個遊標基表中不存在唯一索引。
其他
READ ONLY選項:說明定義只讀遊標。
UPDATE [OF 列名字表]選項:定義遊標可修改的列。如果使用OF 列名字表選項,說明只允許修改所指定的列,否則,所有列均可修改。 
例如,查詢教師名字和所教的課程名,定義遊標TCURSOR的語句如下 :
DECLARE TCURSOR CURSOR FOR 
SELECT tname, cname 
FROM teacher ,couse
WHERE teacher.tno = couse.tno 
2. 打開遊標
打開遊標語句執行遊標定義中的查詢語句,查詢結果存放在遊標緩衝區中。並使遊標指針指向遊標區中的第一個元組,作爲遊標的缺省訪問位置。查詢結果的內容取決與查詢語句的設置和查詢條件。
打開遊標的語句格式:
EXEC SQL OPEN 〈遊標名〉
如果打開的遊標爲INSENSITIVE遊標,在打開時將產生一個臨時表,將定義的遊標數據集合從其基表中拷貝過來。 
SQL Server中,遊標打開後,可以從全局變量@@CURSOR_ROWS中讀取遊標結果集合中的行數。
例1:打開前面所創建的查詢教師姓名和所教課名稱的遊標。
OPEN tcursor
例2:顯示遊標結果集合中數據行數
SELECT 數據行數 = @@CURSOR_ROWS

3. 讀遊標區中的當前元組
讀遊標區數據語句是讀取遊標區中當前元組的值,並將各分量依次賦給指定的共享主變量。FETCH語句用於讀取遊標中的數據,語句格式爲:
FETCH [[NEXT|PRIOR|FIRST|LAST| ABSOLUTE n| RELATIVE n] 
FROM ] 遊標名
[INTO @變量1, @變量2, ….]
其中:
NEXT:說明讀取遊標中的下一行,第一次對遊標實行讀取操作時,NEXT返回結果集合中的第一行。
PRIOR、FIRST、LAST、ABSOLUTE n 和RELATIVE n 選項只適用於SCROLL遊標。它們分別說明讀取遊標中的上一行、第一行、最後一行、第n 行和相對於當前位置的第n 行。n 爲負值時,ABSOLUTE n 和RELATIVE n 說明讀取從遊標結果集合中的最後一行或當前行倒數n行的數據。
INTO子句 說明將讀取的數據存放到指定的局部變量中,每一個變量的數據類型應與遊標所返回的數據類型嚴格匹配,否則將產生錯誤。 
如果遊標區的元組已經讀完,那麼系統狀態變量SQLSTATE的值被設爲02000,意爲"no tuple found"。
例如,讀取tcursor中當前位置後的第二行數據
FETCH RELATIVE 2 FROM tcursor

4. 利用遊標修改數據
SQL Server中的 UPDATE語句 和 DELETE語句也支持遊標操作,它們可以通過遊標修改或刪除遊標基表中的當前數據行。
UPDATE語句的格式爲:
UPDATE table_name
SET 列名=表達式}[,…n]
WHERE CURRENT OF cursor_name
DELETE語句的格式爲:
DELETE FROM table_name
WHERE CURRENT OF cursor_name
說明:
CURRENT OF cursor_name:
表示當前遊標指針所指的當前行數據。CURRENT OF 只能在UPDATE和DELETE語句中使用。
注意:
o使用遊標修改基表數據的前提是聲明的遊標是可更新的。 
o 對相應的數據庫對象(遊標的基表)有修改和刪除權限。 
5. 關閉遊標
關閉遊標後,遊標區的數據不可再讀。CLOSE語句關閉已打開的遊標,之後不能對遊標進行讀取等操作,但可以使用OPEN語句再次打開該遊標。
CLOSE語句的格式爲:
CLOSE 遊標名
例如:關閉tcursor遊標如下描述:
CLOSE tcursor

6 刪除遊標語句
DEALLOCATE語句刪除定義遊標的數據結構,刪除後不可再用。語句格式:
DEALLOCATE 遊標名
例如,刪除tcursor遊標
DEALLOCATE tcursor

例1,讀JS2001班的學生的學號和姓名:
#define MAX 30
EXEC SQL BEGIN DECLARE SECTION;
char TN[12], FU[20]; //定義主變量//
EXEC SQL END DECLARE SECTION; 
char tarn1[30][12],tarn2[30][20]; //定義 C 變量//
. . . . . .
EXEC SQL //執行SQL語句,定義遊標//
DCLARE Scursor CURSOR FOR //聲明遊標Scursor//
SELECT sno,sname //查詢sno,sname//
FROM student //對student表chax 查詢//
WHERE sclass = 'JS2001'; //sclass='JS2001'的班級//
EXEC SQL OPEN Scursor ; //打開遊標//
for (i=0; i<MAX; i++) 
{ EXEC SQL FETCH FROM Scursor
INTO @TN, @FU; //取到宿主變量//
tarn1= TN; //賦值到C數組變量// 
tarn2= FU;
}
.................... 
EXEC SQL CLOSE Scursor ; //關閉遊標//
EXEC SQL DEALLOCATE Scursor ; //刪除遊標//

例2,定義遊標,使結果集包括 pubs 數據庫的 authors 表中的所有行和列。因爲沒指定 SCROLL 選項,FETCH NEXT 是唯一可用的提取選項。
DECLARE authors_cursor CURSOR FOR //聲明遊標authors_cursor //
SELECT * FROM authors 
OPEN authors_cursor //打開遊標authors_cursor //
FETCH NEXT FROM authors_cursor //讀遊標authors_cursor中的一行 //
.................... 

例3, 定義和使用滾動遊標
DECLARE tcursor SCROLL CURSOR FOR 
SELECT tname, cname FROM teacher ,couse
WHERE teacher.tno = couse.tno;
OPEN tcursor; 
取tcursor中當前位置向下的第二行數據
FETCH RELATIVE 2 FROM tcursor
取tcursor中最後一行數據
FETCH LAST FROM tcursor
取tcursor中當前位置向前的第4行數據
FETCH RELATIVE -4 FROM tcursor

例4 利用 @@FETCH_STATUS 控制一個 WHILE 循環中的遊標活動。
DECLARE S_Cursor CURSOR FOR 
SELECT sname, sno FROM student 
OPEN S_Cursor 
FETCH NEXT FROM S_Cursor 
WHILE @@FETCH_STATUS = '000000'
BEGIN FETCH NEXT FROM S_Cursor END
CLOSE S_Cursor 
DEALLOCATE S_Cursor 

例5,職工普調工資,從最低工資調起,每人工資長10%,但工資總額不能超過50萬元。當調完某個職工工資後,如果工資總額達到或超過50萬元,就不再調 了,另外,如果職工全部調了一遍,工資總額還沒到50萬元,也到此爲止。現有職工表emp,定義了一個遊標cl,遊標的查詢語句取出職工號和工資值,並按 增序排列。下面是程序代碼: 
void addsalary()
{ EXEC SQL BEGIN DECLARE SECTION //聲明SQL變量//
char empno[8], e_sno,SQLSTATE[6];
float s_sal, e_sal;
EXEC SQL END DECLARE SECTION; //聲明SQL變量完//
EXEC SQL DECLARE cl CURSOR FOR //定義遊標 cl ,對emp表的eno,sal列可以作任何操作
SELECT eno, sal 
FROM emp 
ORDER BY sal ASC;
EXEC SQL OPEN cl; //打開遊標/
EXEC SQL SELECT SUM(sal) INTO @s_sal FROM emp; //取工資總和到s_sal 
while(s_sal < 500000.00)
{
EXEC SQL FETCH FROM cl
INTO @e_sno , @e_sal; //從遊標中讀出的數據放入e_sno,e_sal變量
If(SQLSTATE='02000') BREAK; //讀完記錄,退出//
EXEC SQL UPDATE emp 
SET sal=sal*1.1 //遊標內容更新,將empno=e_sno相應的sal*1.1
WHERE empno=@e_eno;
s_sal = s_sal+ e_sal *0.1; //計算工資總和到s_sal
};
EXEC SQL CLOSE cl; /關閉遊標/} 

 SQL Server提供兩種遊標應用接口方法:第一種是符合ANSI標準的SQL遊標語句,它們可以實現聲明、打開、讀取或關閉遊標操作,這些語句可用在 Transact_SQL語句或存儲過程內;第二種是庫函數形式,客戶端的DB_Library 或ODBC應用程序可以調用這些函數。
 遊標語句增強了Transact_SQL對集合數據的處理能力,在SQL Server中,通過遊標還可以修改或刪除基表中的數據。

7,使用遊標時應注意的問題:
(1) 儘管使用遊標比較靈活,可以實現對數據集中單行數據的直接操作,但遊標會在下面幾個方面影響系統的性能:
-使用遊標會導致頁鎖與表鎖的增加
-導致網絡通信量的增加
-增加了服務器處理相應指令的額外開銷
(2) 使用遊標時的優化問題:
-明確指出遊標的用途:for read only或for update
-在for update後指定被修改的列


本文轉自:http://blog.csdn.net/a3676212/article/details/4038943

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章