1 什么是游標:
關系數據庫中的操作會對整個行集起作用。 例如,由 SELECT 語句返回的行集包括滿足該語句的 WHERE 子句中條件的所有行。 這種由語句返回的完整行集稱為結果集。 應用程序,特別是交互式聯機應用程序,并不總能將整個結果集作為一個單元來有效地處理。 這些應用程序需要一種機制以便每次處理一行或一部分行。 游標就是提供這種機制的對結果集的一種擴展。
游標通過以下方式來擴展結果處理:
- 允許定位在結果集的特定行。
- 從結果集的當前位置檢索一行或一部分行。
- 支持對結果集中當前位置的行進行數據修改。
- 為由其他用戶對顯示在結果集中的數據庫數據所做的更改提供不同級別的可見性支持。
- 提供腳本、存儲過程和觸發器中用于訪問結果集中的數據的 Transact-SQL 語句。
——MSDN
不難理解,游標與其他數據庫操作的最大不同就是對象是單條記錄而不是結果集,一般用于過程化程序里嵌入的SQL語句。在數據庫服務程序里用到了自動隱含創建的游標。
2 基本用法:
2.1 聲明游標
DECLARE 游標名 CURSOR
FOR SELECT語句
2.2 打開游標
OPEN 游標名
2.3 從游標獲取數據
FETCH NEXT FROM 游標名 [ INTO FETCH_LIST ]
從游標獲取數據需要注意可能到達游標末尾,以下方法解決這個問題以避免用戶在關閉游標時產生錯誤
1 BEGIN 2 DECLARE @custname VARCHAR(20) 3 DECLARE namecursor CURSOR FOR SELECT CUST_NAME FROM TBL_CUSTOMER OPEN namecursor 4 FETCH NEXT FROM namecursor INTO @custname 5 WHILE (@@FETCH_STATUS <> -1) 6 BEGIN 7 IF (@@FETCH_STATUS <> -2) 8 BEGIN 9 --操作游標變量10 END11 FETCH NEXT FROM namecursor INTO @custname12 END13 CLOSE namecursor14 DEALLOCATE namecursor15 END
2.4 關閉游標
CLOSE 游標名
關閉后不能對游標進行讀取等操作,但可以使用OPEN語句再次打開
2.5 釋放游標
DEALLOCATE 游標名
即刪除游標,不可再使用
3 一個有意思的小例子:
雖然知道了游標的概念和基本用法,但對于什么時候用游標還很模糊,甚至誤認為游標可以被子查詢所代替。直到遇到了這個有意思的小例子:
表結構如下:
題目要求是:列出從事同一種工作但屬于不同部門的雇員的不同組合
即如下結果:
在想盡了子查詢、表連接、建臨時表等等辦法之后,我發現我遇到了一個不可逾越的障礙:無法排除兩個名字組合的唯一性。即:我得到的結果可能是如下
ANAME | BNAME |
Adams | James |
James | Adams |
最終我想到了剛學到的游標,代碼如下
1 SELECT A.Ename AS ANAME, B.Ename AS BNAME 2 INTO #t 3 FROM EMP A 4 JOIN EMP B 5 ON A.job = B.job AND A.deptNo <> B.deptNo and A.Ename<>b.Ename 6 ORDER BY ANAME 7 8 --DROP TABLE #t 9 10 DECLARE TEST_CURSOR CURSOR FOR11 SELECT ANAME, BNAME FROM #t12 13 OPEN TEST_CURSOR14 DECLARE @ANAME VARCHAR(20)15 DECLARE @BNAME VARCHAR(20)16 17 FETCH NEXT FROM TEST_CURSOR INTO @ANAME, @BNAME18 DELETE FROM #t WHERE ANAME=@BNAME AND BNAME=@ANAME19 WHILE @@FETCH_STATUS = 020 BEGIN 21 FETCH NEXT FROM TEST_CURSOR INTO @ANAME, @BNAME22 DELETE FROM #t WHERE ANAME=@BNAME AND BNAME=@ANAME23 END24 25 CLOSE TEST_CURSOR26 DEALLOCATE TEST_CURSOR27 28 SELECT * FROM #t
--------------------------------------------------------------------------------------
--12.2更新:
突然發現這題可以用極其簡單的方法寫出來,用游標簡直Stupid~~
1 SELECT A.Ename AS ANAME, B.Ename AS BNAME 2 FROM EMP A, EMP B3 WHERE A.job = B.job AND A.deptNo <> B.deptNo AND A.Ename < B.Ename4 ORDER BY ANAME
掩面遁走~~
新聞熱點
疑難解答