從一個小例子認識SQL游標


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     END
11     FETCH NEXT FROM namecursor INTO @custname
12 END
13 CLOSE namecursor
14 DEALLOCATE namecursor
15 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 FOR
11 SELECT ANAME, BNAME FROM #t
12 
13 OPEN TEST_CURSOR
14 DECLARE @ANAME VARCHAR(20)
15 DECLARE @BNAME VARCHAR(20)
16 
17 FETCH NEXT FROM TEST_CURSOR INTO @ANAME, @BNAME
18 DELETE FROM #t WHERE ANAME=@BNAME AND BNAME=@ANAME
19 WHILE @@FETCH_STATUS = 0
20 BEGIN 
21     FETCH NEXT FROM TEST_CURSOR INTO @ANAME, @BNAME
22     DELETE FROM #t WHERE ANAME=@BNAME AND BNAME=@ANAME
23 END
24 
25 CLOSE TEST_CURSOR
26 DEALLOCATE TEST_CURSOR
27 
28 SELECT * FROM #t

--------------------------------------------------------------------------------------

--12.2更新:

突然發現這題可以用極其簡單的方法寫出來,用游標簡直Stupid~~

1 SELECT A.Ename AS ANAME, B.Ename AS BNAME 
2 FROM EMP A, EMP B
3 WHERE A.job = B.job AND A.deptNo <> B.deptNo AND A.Ename < B.Ename
4 ORDER BY ANAME

掩面遁走~~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM