<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          這該死的游標(biāo),怎么這么難呢?

          共 3343字,需瀏覽 7分鐘

           ·

          2020-09-10 14:49

          點(diǎn)擊上方SQL數(shù)據(jù)庫開發(fā),關(guān)注獲取SQL視頻教程


          SQL專欄

          SQL數(shù)據(jù)庫基礎(chǔ)知識(shí)匯總

          SQL數(shù)據(jù)庫高級(jí)知識(shí)匯總

          經(jīng)常有小伙伴吐槽SQL中最難的可能就是游標(biāo)了,游標(biāo)確實(shí)不好理解,我們常見的數(shù)據(jù)操作都是返回一個(gè)結(jié)果集,而游標(biāo)則是返回單行記錄。


          今天我們就來給小伙伴們講解一下這“該死”的游標(biāo),該如何使用。


          1 、什么是游標(biāo)

          關(guān)系數(shù)據(jù)庫中的操作會(huì)對(duì)整個(gè)行集起作用。例如,由 SELECT 語句返回的行集包括滿足該語句的 WHERE 子句中條件的所有行。這種由語句返回的完整行集稱為結(jié)果集。應(yīng)用程序,特別是交互式聯(lián)機(jī)應(yīng)用程序,并不總能將整個(gè)結(jié)果集作為一個(gè)單元來有效地處理。這些應(yīng)用程序需要一種機(jī)制以便每次處理一行或一部分行。游標(biāo)就是提供這種機(jī)制的對(duì)結(jié)果集的一種擴(kuò)展。

          游標(biāo)通過以下方式來擴(kuò)展結(jié)果處理:

          • 允許定位在結(jié)果集的特定行。

          • 從結(jié)果集的當(dāng)前位置檢索一行或一部分行。

          • 支持對(duì)結(jié)果集中當(dāng)前位置的行進(jìn)行數(shù)據(jù)修改。

          • 為由其他用戶對(duì)顯示在結(jié)果集中的數(shù)據(jù)庫數(shù)據(jù)所做的更改提供不同級(jí)別的可見性支持。

          • 提供腳本、存儲(chǔ)過程和觸發(fā)器中用于訪問結(jié)果集中的數(shù)據(jù)的 Transact-SQL 語句。?

          不難理解,游標(biāo)與其他數(shù)據(jù)庫操作的最大不同就是對(duì)象是單條記錄而不是結(jié)果集,一般用于過程化程序里嵌入的SQL語句。在數(shù)據(jù)庫服務(wù)程序里用到了自動(dòng)隱含創(chuàng)建的游標(biāo)。

          ?

          2 、基本用法

          2.1 聲明游標(biāo)

          DECLARE 游標(biāo)名 CURSOR

          FOR SELECT語句


          2.2 打開游標(biāo)

          OPEN 游標(biāo)名


          2.3 從游標(biāo)獲取數(shù)據(jù)

          FETCH NEXT | PRIOR | FIRST | LAST |?

          ?ABSOLUTE{?n| @nvar}?|

          RELATIVE?{?n| @nvar}

          FROM 游標(biāo)名 [ INTO FETCH_LIST ]

          這里要注意的是獲取游標(biāo)里的數(shù)據(jù),除了常用的FETCH NEXT(獲取下一行),SQL Server提供了6種定位選項(xiàng):

          NEXT
          緊跟當(dāng)前行返回結(jié)果行,并且當(dāng)前行遞增為返回行。?如果?FETCH NEXT?為對(duì)游標(biāo)的第一次提取操作,則返回結(jié)果集中的第一行。?NEXT?為默認(rèn)的游標(biāo)提取選項(xiàng)。
          PRIOR
          返回緊鄰當(dāng)前行前面的結(jié)果行,并且當(dāng)前行遞減為返回行。?如果?FETCH PRIOR?為對(duì)游標(biāo)的第一次提取操作,則沒有行返回并且游標(biāo)置于第一行之前。
          FIRST
          返回游標(biāo)中的第一行并將其作為當(dāng)前行。
          LAST
          返回游標(biāo)中的最后一行并將其作為當(dāng)前行。
          ABSOLUTE {?n| @nvar}
          如果 n 或 @nvar 為正,則返回從游標(biāo)起始處開始向后的第 n 行,并將返回行變成新的當(dāng)前行******。?如果 n 或 @nvar 為負(fù),則返回從游標(biāo)末尾處開始向前的第 n 行,并將返回行變成新的當(dāng)前行******。?如果 n 或 @nvar 為 0,則不返回行****。?n 必須是整數(shù)常量,并且 @nvar 必須是 smallint、tinyint 或 int。
          RELATIVE {?n| @nvar}
          如果 n 或 @nvar 為正,則返回從當(dāng)前行開始向后的第 n 行,并將返回行變成新的當(dāng)前行******。?如果 n 或 @nvar 為負(fù),則返回從當(dāng)前行開始向前的第 n 行,并將返回行變成新的當(dāng)前行******。?如果 n 或 @nvar 為 0,則返回當(dāng)前行****。?在對(duì)游標(biāo)進(jìn)行第一次提取時(shí),如果在將 n 或 @nvar 設(shè)置為負(fù)數(shù)或 0 的情況下指定?FETCH RELATIVE,則不返回行****。?n 必須是整數(shù)常量,并且 @nvar 必須是 smallint、tinyint 或 int。

          從游標(biāo)獲取數(shù)據(jù)需要注意可能到達(dá)游標(biāo)末尾,以下方法解決這個(gè)問題以避免用戶在關(guān)閉游標(biāo)時(shí)產(chǎn)生錯(cuò)誤
          --開始一個(gè)事務(wù)
          BEGIN
          --定義一個(gè)變量和一個(gè)游標(biāo)
          ???DECLARE?@custname VARCHAR(20)
          ???DECLARE?namecursor CURSOR?FOR?
          --打開游標(biāo),并從游標(biāo)中獲取數(shù)據(jù),然后插入變量中
          ?????SELECT?CUST_NAME FROM?TBL_CUSTOMER OPEN?namecursor
          ???FETCH?NEXT?FROM?namecursor INTO?@custname
          --當(dāng)FETCH 語句失敗或此行不在結(jié)果集中時(shí),執(zhí)行下面的IF語句
          ???WHILE?(@@FETCH_STATUS <> -1)
          ???BEGIN
          --如果被提取的行不存在,執(zhí)行下面的事務(wù)
          ???????IF?(@@FETCH_STATUS <> -2)
          ???????BEGIN
          ???????--操作游標(biāo)變量
          ???END

          ???FETCH?NEXT?FROM?namecursor INTO?@custname
          END
          CLOSE?namecursor
          DEALLOCATE?namecursor
          END


          其中上面的WHILE語句和IF語句中有個(gè)系統(tǒng)參數(shù)@@FETCH_STATUS,是MicroSoft SQL SERVER的一個(gè)全局變量,它有三個(gè)值:
          • 0? ?FETCH 語句成功

          • -1? FETCH 語句失敗或此行不在結(jié)果集中

          • -2? 被提取的行不存在


          2.4 關(guān)閉游標(biāo)

          CLOSE 游標(biāo)名

          關(guān)閉后不能對(duì)游標(biāo)進(jìn)行讀取等操作,但可以使用OPEN語句再次打開


          2.5 釋放游標(biāo)

          DEALLOCATE 游標(biāo)名

          即刪除游標(biāo),不可再使用

          ?

          3、游標(biāo)示例

          雖然知道了游標(biāo)的概念和基本用法,但對(duì)于什么時(shí)候用游標(biāo)還很模糊,甚至誤認(rèn)為游標(biāo)可以被子查詢所代替。直到遇到了這個(gè)有意思的小例子:
          表結(jié)構(gòu)如下:

          題目要求是:列出從事同一種工作但屬于不同部門的雇員的不同組合

          即如下結(jié)果:

          在想盡了子查詢、表連接、建臨時(shí)表等等辦法之后,我發(fā)現(xiàn)我遇到了一個(gè)不可逾越的障礙:無法排除兩個(gè)名字組合的唯一性。即:我得到的結(jié)果可能是如下


          ?最終我們用游標(biāo),代碼如下:
          SELECT A.Ename AS ANAME, B.Ename AS BNAME
          INTO #t
          FROM EMP A
          JOIN EMP B
          ON A.job = B.job AND A.deptNo <> B.deptNo and A.Ename<>b.Ename
          ORDER BY ANAME

          --DROP TABLE #t

          DECLARE TEST_CURSOR CURSOR FOR
          SELECT ANAME, BNAME FROM #t

          OPEN TEST_CURSOR
          ?DECLARE @ANAME VARCHAR(20)
          ?DECLARE @BNAME VARCHAR(20)

          ?FETCH NEXT FROM TEST_CURSOR INTO @ANAME, @BNAME
          ?DELETE FROM #t WHERE ANAME=@BNAME AND BNAME=@ANAME
          ?WHILE @@FETCH_STATUS = 0
          ?BEGIN
          ? ?FETCH NEXT FROM TEST_CURSOR INTO @ANAME, @BNAME
          ? ?DELETE FROM #t WHERE ANAME=@BNAME AND BNAME=@ANAME
          ?END

          CLOSE TEST_CURSOR
          DEALLOCATE TEST_CURSOR

          SELECT * FROM #t


          以上就是游標(biāo)的一些簡(jiǎn)單介紹,其實(shí)工作中不到萬不得已,一般不會(huì)使用游標(biāo),因?yàn)閷?duì)于數(shù)據(jù)量大的表使用游標(biāo),那執(zhí)行效率絕對(duì)是個(gè)災(zāi)難。


          SQL講究的是簡(jiǎn)單才是王道,切勿為了追求什么騷操作把數(shù)據(jù)庫給整垮了,切記!


          ——End——

          后臺(tái)回復(fù)關(guān)鍵字:1024,獲取一份精心整理的技術(shù)干貨
          后臺(tái)回復(fù)關(guān)鍵字:進(jìn)群,帶你進(jìn)入高手如云的交流群。
          推薦閱讀

          這是一個(gè)能學(xué)到技術(shù)的公眾號(hào),歡迎關(guān)注
          點(diǎn)擊「閱讀原文」了解SQL訓(xùn)練營(yíng)

          瀏覽 47
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美一级A片免费看视频小说 | 日本乱伦一区二区三区 | 日韩一本道在线 | 一区二区导航 | 青娱乐国产视频 |