這次簡單說說游標(biāo)的分類。
先看看通常游標(biāo)的語法
DECLARE cursor_name CURSOR [ LOCAL :局部游標(biāo),僅在當(dāng)前會(huì)話有效 | GLOBAL : 全局游標(biāo),全局有效,可以 ] [ FORWARD_ONLY :只能向前游標(biāo),讀取游標(biāo)時(shí)只能使用 Next 謂詞 | SCROLL :滾動(dòng)游標(biāo),FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE 都可以使用 ] [ STATIC :定義一個(gè)游標(biāo),以創(chuàng)建將由該游標(biāo)使用的數(shù)據(jù)的臨時(shí)復(fù)本。對(duì)游標(biāo)的所有請(qǐng)求都從 tempdb 中的這一臨時(shí)表中得到應(yīng)答; | KEYSET :對(duì)基表中的非鍵值所做的更改(由游標(biāo)所有者更改或由其他用戶提交)可以在用戶滾動(dòng)游標(biāo)時(shí)看到。其他用戶執(zhí)行的插入是不可見的(不能通過 Transact-SQL 服務(wù)器游標(biāo)執(zhí)行插入)。如果刪除某一行,則在嘗試提取該行時(shí)返回值為 -2 的 @@FETCH_STATUS。 | DYNAMIC :定義一個(gè)游標(biāo),以反映在滾動(dòng)游標(biāo)時(shí)對(duì)結(jié)果集內(nèi)的各行所做的所有數(shù)據(jù)更改。行的數(shù)據(jù)值、順序和成員身份在每次提取時(shí)都會(huì)更改。動(dòng)態(tài)游標(biāo)不支持 ABSOLUTE 提取選項(xiàng) | FAST_FORWARD :指定啟用了性能優(yōu)化的 FORWARD_ONLY、READ_ONLY 游標(biāo)。如果指定了 SCROLL 或 FOR_UPDATE,則不能也指定 FAST_FORWARD ] [ READ_ONLY :只讀游標(biāo),不能對(duì)游標(biāo)內(nèi)容進(jìn)行更改,不能使用 where current of 語句 | SCROLL_LOCKS :指定通過游標(biāo)進(jìn)行的定位更新或刪除一定會(huì)成功。將行讀入游標(biāo)時(shí) SQL Server 將鎖定這些行,以確保隨后可對(duì)它們進(jìn)行修改。 | OPTIMISTIC :指定如果行自讀入游標(biāo)以來已得到更新,則通過游標(biāo)進(jìn)行的定位更新或定位刪除不成功。當(dāng)將行讀入游標(biāo)時(shí),SQL Server 不鎖定行
] [ TYPE_WARNING ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] :制定那些列可以進(jìn)行更新,如果不填,則默認(rèn)全部可以更新 ]好了,拋完書包之后,現(xiàn)在問題來了,本人盡量圖文并茂的描述每種類型的特點(diǎn)吧……_(:з」∠)_--------------------------------------------------------------我是分割線-----------------------------------------------------------------------------------------------------------------------------------------------測試表的結(jié)構(gòu)
CREATE TABLE [dbo].[Employee]([ID] [int] NOT NULL IDENTITY(1, 1) primary key,[NAME] [nvarchar] (50) NULL,[Name2] [varchar] (50) NULL) ON [PRIMARY]GO
FORWARD_ONLY 和 SCROLL 這兩者在用的過程中還是比較好區(qū)別。一個(gè)只能前進(jìn),一個(gè)可以前滾翻后滾翻什么的。先看看
FORWARD_ONLY
DECLARE CR_CURSOR CURSOR FAST_FORWARD --這個(gè)游標(biāo),是一個(gè)只讀游標(biāo)而已哦~FOR SELECT ID , NAME FROM dbo.Employee WHERE ID >= 24 DECLARE @ID INT , @Name NVARCHAR(50) OPEN CR_CURSORFETCH NEXT FROM CR_CURSOR INTO @ID, @NameWHILE @@FETCH_STATUS = 0 BEGIN --UPDATE dbo.Employee SET Name2 = @Name WHERE CURRENT OF CR_CURSOR 因?yàn)槭侵蛔x游標(biāo),所以是不允許修改游標(biāo)本身內(nèi)容 UPDATE dbo.Employee SET Name2 = @Name WHERE ID = @ID FETCH NEXT FROM CR_CURSOR INTO @ID, @Name ENDCLOSE CR_CURSORDEALLOCATE CR_CURSOR
然后我們看看執(zhí)行計(jì)劃,這個(gè)就跟普通的即時(shí)查詢時(shí)沒有任何區(qū)別的,所以我猜測,假如在游標(biāo)讀取過程中,數(shù)據(jù)發(fā)生了變化,是可以獲取出來的。下面我來驗(yàn)證一下
1、在讀取之前,我先溫柔的刪除Employee 表里面,ID = 25的記錄
DELETE FROM dbo.Employee WHERE ID = 25
2、然后在讀取游標(biāo)里面開啟單步調(diào)試,讀到ID = 24的節(jié)點(diǎn)
3、然后在讀下一個(gè)游標(biāo)之前,我添加了一條數(shù)據(jù)
SET IDENTITY_INSERT Employee ONINSERT INTO dbo.Employee (ID,NAME )VALUES ( 25,N'我是插進(jìn)來的小三')SET IDENTITY_INSERT Employee OFF
然后繼續(xù)F10前進(jìn) ~咦~~25出來了野~
證明了,F(xiàn)ORWARD_ONLY 這貨是在游標(biāo)向下滾動(dòng)的時(shí)候即使獲取數(shù)據(jù)的。所以能捕捉到新插入或刪除的數(shù)據(jù)。大致是這樣紙了,下面在看看
SCROLL
DECLARE CR_CURSOR CURSOR SCROLL --代碼基本一致,只是換成了 SCROLLFOR SELECT ID , NAME FROM dbo.Employee WHERE ID >= 24 DECLARE @ID INT , @Name NVARCHAR(50) OPEN CR_CURSORFETCH NEXT FROM CR_CURSOR INTO @ID, @NameWHILE @@FETCH_STATUS = 0 BEGIN UPDATE dbo.Employee SET Name2 = @Name WHERE CURRENT OF CR_CURSOR --這句現(xiàn)在可以執(zhí)行了 FETCH NEXT FROM CR_CURSOR INTO @ID, @Name ENDCLOSE CR_CURSORDEALLOCATE CR_CURSOR
慣例先看看這個(gè)執(zhí)行計(jì)劃吧~可以看到有一個(gè)查詢過程要把數(shù)據(jù)插入到 CWT_PrimaryKey 的臨時(shí)表里面。那我猜想,如果在游標(biāo)讀取途中,外部有數(shù)據(jù)的增加,是獲取不到的了,那如果更新和刪除會(huì)怎么樣呢?實(shí)驗(yàn)一下
1、在讀取之前,我還是先溫柔的刪除Employee 表里面,ID = 25的記錄
DELETE FROM dbo.Employee WHERE ID = 25
2、然后在讀取游標(biāo)里面開啟單步調(diào)試,讀到ID = 24的節(jié)點(diǎn)
3、然后在讀下一個(gè)游標(biāo)之前,我添加了一條數(shù)據(jù)
SET IDENTITY_INSERT Employee ONINSERT INTO dbo.Employee (ID,NAME )VALUES ( 25,N'我是插進(jìn)來的小三')SET IDENTITY_INSERT Employee OFF
然后F10……ID25沒有粗線_(:з」∠)_直接到26去了
確實(shí),外部新增了數(shù)據(jù),是獲取不到的。下面測一下修改和刪除。
1、然后在讀取游標(biāo)里面開啟單步調(diào)試,讀到ID = 24的節(jié)點(diǎn)
2、修改ID是25的數(shù)據(jù)
UPDATE dbo.Employee SET NAME = '我是修改了的ID25哦' WHERE ID = 25
3、然后按F10繼續(xù)走,是可以獲取的喲~
刪除呢?重試一遍,在單步的過程中直接將 ID = 25的數(shù)據(jù)抹掉,然后就直接循環(huán)結(jié)束了~查了一下 @@Fetch_Status = -2 提取數(shù)據(jù)失敗,當(dāng)然啦……數(shù)據(jù)都被刪除了。順帶一提,如果繼續(xù)往下取,還是可以取到下一條數(shù)據(jù)的喲~……圖就不截了。。。
然后在繼續(xù)試下各種方式,再進(jìn)行補(bǔ)充
新聞熱點(diǎn)
疑難解答
圖片精選