日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

SQLServer游标详解

發(fā)布時(shí)間:2023/12/20 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQLServer游标详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

參考資料
http://technet.microsoft.com/zh-cn/library/ms181441(v=sql.105).aspx
一、游標(biāo)概念
我們知道,關(guān)系數(shù)據(jù)庫(kù)所有的關(guān)系運(yùn)算其實(shí)是集合與集合的運(yùn)算,它的輸入是集合輸出同樣是集合,有時(shí)需要對(duì)結(jié)果集逐行進(jìn)行處理,這時(shí)就需要用到游標(biāo)。我們對(duì)游標(biāo)的使用一本遵循“五步法”:聲明游標(biāo)—>打開(kāi)游標(biāo)—>讀取數(shù)據(jù)—>關(guān)閉游標(biāo)—>刪除游標(biāo)。以下就從這五步對(duì)游標(biāo)的使用進(jìn)行說(shuō)明,并給出具體實(shí)例。

二、“五步法”講解
1、聲明游標(biāo)(DECLARE CURSOR)
(1) DECLARE CURSOR 既接受基于 ISO 標(biāo)準(zhǔn)的語(yǔ)法,也接受使用一組 Transact-SQL 擴(kuò)展的語(yǔ)法。
復(fù)制代碼
ISO 語(yǔ)法
DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSOR
FOR select_statement
[ FOR { READ ONLY | UPDATE [ OF column_name [ ,…n ] ] } ]
[;]

Transact-SQL 擴(kuò)展語(yǔ)法
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] (說(shuō)明游標(biāo)的“作用域”)
[ FORWARD_ONLY | SCROLL ] (說(shuō)明游標(biāo)的“方向”)
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] (“說(shuō)明游標(biāo)的“類(lèi)型”)
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
[ TYPE_WARNING ]
FOR select_statement
[ FOR UPDATE [ OF column_name [ ,…n ] ] ]
[;]
復(fù)制代碼
下面只對(duì)“T-SQL擴(kuò)展語(yǔ)法”進(jìn)行介紹,主要游標(biāo)介紹作用域、方向及類(lèi)型

(2)游標(biāo)的作用域
LOCAL

說(shuō)明所聲明的游標(biāo)為局部的,其作用域?yàn)閯?chuàng)建它的批處理、存儲(chǔ)過(guò)程或觸發(fā)器,即在批處理、調(diào)用它的存儲(chǔ)過(guò)程或觸發(fā)器執(zhí)行完成后,該游標(biāo)被系統(tǒng)隱式釋放。但,若游標(biāo)作為存儲(chǔ)過(guò)程O(píng)UTPUT 的輸出參數(shù),在存儲(chǔ)過(guò)程終止后給游標(biāo)變量分配參數(shù)可以繼續(xù)引用游標(biāo),如果 OUTPUT 參數(shù)將游標(biāo)傳遞回來(lái),則游標(biāo)在最后引用它的變量釋放或離開(kāi)作用域時(shí)釋放。

GLOBAL

指定該游標(biāo)的作用域?qū)?lái)說(shuō)連接是全局的。在由連接執(zhí)行的任何存儲(chǔ)過(guò)程或批處理中,都可以引用該游標(biāo)名稱(chēng)。該游標(biāo)僅在斷開(kāi)連接時(shí)隱式釋放。注意:如果 GLOBAL 和 LOCAL 參數(shù)都未指定,則默認(rèn)值由 default to local cursor 數(shù)據(jù)庫(kù)選項(xiàng)的設(shè)置控制。在 SQL Server 7.0 版中,該選項(xiàng)默認(rèn)為 FALSE,以便與 SQL Server 的早期版本匹配,在早期版本中,所有游標(biāo)都是全局的。

復(fù)制代碼
declare testcur cursor --聲明時(shí)未指定"local"或"global"關(guān)鍵字,系統(tǒng)默認(rèn)游標(biāo)是"global(全局)"的.
for
select 學(xué)號(hào),姓名 from XSB
GO
open testcur
fetch next from testcur
GO

declare testcur cursor local --聲明時(shí)指定"local"關(guān)鍵字
for
select 學(xué)號(hào),姓名 from XSB
open testcur
fetch next from testcur
GO --在這個(gè)批處理結(jié)束后,游標(biāo)自動(dòng)釋放,即失效

declare testcur1 cursor local --聲明時(shí)指定"local"關(guān)鍵字
for
select 學(xué)號(hào),姓名 from XSB
GO --在這個(gè)批處理后,游標(biāo)就失效了,后面對(duì)游標(biāo)操作時(shí),提示"名為 ‘testcur1’ 的游標(biāo)不存在"錯(cuò)誤.
open testcur1
fetch next from testcur1
GO
復(fù)制代碼
(3)游標(biāo)方向
FORWARD_ONLY

指定游標(biāo)只能從第一行滾動(dòng)到最后一行。FETCH NEXT 是唯一支持的提取選項(xiàng)。如果在指定 FORWARD_ONLY 時(shí)不指定 STATIC、KEYSET 和 DYNAMIC 關(guān)鍵字,則游標(biāo)作為 DYNAMIC 游標(biāo)進(jìn)行操作。如果 FORWARD_ONLY 和 SCROLL 均未指定,則除非指定 STATIC、KEYSET 或 DYNAMIC 關(guān)鍵字,否則默認(rèn)為 FORWARD_ONLY。STATIC、KEYSET 和 DYNAMIC 游標(biāo)默認(rèn)為 SCROLL。與 ODBC 和 ADO 這類(lèi)數(shù)據(jù)庫(kù) API 不同,STATIC、KEYSET 和 DYNAMIC Transact-SQL 游標(biāo)支持 FORWARD_ONLY。

SCROLL

指定所有的提取選項(xiàng)(FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE)均可用。如果未在 ISO DECLARE CURSOR 中指定 SCROLL,則 NEXT 是唯一支持的提取選項(xiàng)。如果也指定了 FAST_FORWARD,則不能指定 SCROLL。

復(fù)制代碼
declare directionCur cursor --不指定移動(dòng)方向,則默認(rèn)為“forward_only”
for
select 學(xué)號(hào),姓名 from XSB
Go
open directionCur
fetch next from directionCur
Go
fetch prior from directionCur --錯(cuò)誤“提取類(lèi)型 prior 不能與只進(jìn)游標(biāo)一起使用。”
Go
close directionCur2
deallocate directionCur2
Go

declare directionCur1 cursor forward_only --指定“forward_only”方向
for
select 學(xué)號(hào),姓名 from XSB
Go
open directionCur1
fetch next from directionCur1
Go
fetch prior from directionCur1 --錯(cuò)誤“提取類(lèi)型 prior 不能與只進(jìn)游標(biāo)一起使用。”
Go
close directionCur2
deallocate directionCur2
Go

declare directionCur2 cursor scroll --指定“scroll”方向
for
select 學(xué)號(hào),姓名 from XSB
Go
open directionCur2
fetch next from directionCur2
Go
fetch prior from directionCur2
Go
close directionCur2
deallocate directionCur2
Go

–結(jié)論:若游標(biāo)沒(méi)有指定任何訪問(wèn)或類(lèi)型參數(shù),則默認(rèn)為全局、只進(jìn)、動(dòng)態(tài)游標(biāo)。(這是在SQLServer2008 R2上的測(cè)試結(jié)果,具體取決于軟件設(shè)置)

–"scroll"和"fast_forward"不能一起使用
declare forwardTest cursor scroll fast_forward --報(bào)錯(cuò)“游標(biāo)選項(xiàng) SCROLL 和 FAST_FORWARD 沖突。”
for
select 學(xué)號(hào),姓名 from XSB
Go

–在 SQL Server 2000 中,FAST_FORWARD 和 FORWARD_ONLY 游標(biāo)選項(xiàng)是互相排斥的。如果指定了二者,則會(huì)引發(fā)錯(cuò)誤。
–在 SQL Server 2005 及更高版本中,這兩個(gè)關(guān)鍵字可以用在同一個(gè) DECLARE CURSOR 語(yǔ)句中。
declare forwardTest1 cursor forward_only fast_forward
for
select * from XSB
Go
復(fù)制代碼
(4)游標(biāo)類(lèi)型
STATIC

定義一個(gè)游標(biāo),以創(chuàng)建將由該游標(biāo)使用的數(shù)據(jù)的臨時(shí)復(fù)本。對(duì)游標(biāo)的所有請(qǐng)求都從 tempdb 中的這一臨時(shí)表中得到應(yīng)答;因此,在對(duì)該游標(biāo)進(jìn)行提取操作時(shí)返回的數(shù)據(jù)中不反映對(duì)基表所做的修改,并且該游標(biāo)不允許修改。及該游標(biāo)是只讀的。

KEYSET

指定當(dāng)游標(biāo)打開(kāi)時(shí),游標(biāo)中行的成員身份和順序已經(jīng)固定。對(duì)行進(jìn)行唯一標(biāo)識(shí)的鍵集內(nèi)置在 tempdb 內(nèi)一個(gè)稱(chēng)為 keyset 的表中。

DYNAMIC

定義一個(gè)游標(biāo),以反映在滾動(dòng)游標(biāo)時(shí)對(duì)結(jié)果集內(nèi)的各行所做的所有數(shù)據(jù)更改。行的數(shù)據(jù)值、順序和成員身份在每次提取時(shí)都會(huì)更改。

FAST_FORWARD

指定啟用了性能優(yōu)化的 FORWARD_ONLY、READ_ONLY 游標(biāo)。如果指定了 SCROLL 或 FOR_UPDATE,則不能也指定 FAST_FORWARD。

2、打開(kāi)游標(biāo)(OPEN)
語(yǔ)法
OPEN { { [ GLOBAL ] cursor_name } | cursor_variable_name }
示例
復(fù)制代碼
–打開(kāi)游標(biāo)并讀取所有行
declare XSBcur cursor --聲明
for
Select * from XSB
Go
open XSBcur --打開(kāi)
fetch next from XSBcur --獲取數(shù)據(jù)
while @@FETCH_STATUS = 0
begin
fetch next from XSBcur
end
close XSBcur --關(guān)閉
deallocate XSBcur --刪除
復(fù)制代碼
全局變量 @@CURSOR_ROWS

該變量保存著最后打開(kāi)的游標(biāo)中的數(shù)據(jù)行數(shù),當(dāng)其值為0時(shí),表示沒(méi)有游標(biāo)打開(kāi);其值為-1時(shí),表示游標(biāo)為動(dòng)態(tài)的;當(dāng)其值為-m(m為正整數(shù))時(shí),游標(biāo)采用異步方式填充,m為當(dāng)前鍵集中已填充的

行數(shù);當(dāng)其值為m(m為正整數(shù))時(shí),游標(biāo)已被完全填充,m是游標(biāo)中的數(shù)據(jù)行數(shù)。

3、讀取數(shù)據(jù)
語(yǔ)法
復(fù)制代碼
FETCH
[ [ NEXT | PRIOR | FIRST | LAST
| ABSOLUTE { n | @nvar }
| RELATIVE { n | @nvar }
]
FROM
]
{ { [ GLOBAL ] cursor_name } | @cursor_variable_name }
[ INTO @variable_name [ ,…n ] ] --into說(shuō)明將讀取的游標(biāo)數(shù)據(jù)存放到指定的變量中
復(fù)制代碼
示例
復(fù)制代碼

declare stuCur cursor scroll
for
select 學(xué)號(hào),姓名 from XSB
GO
open stuCur
Go
–讀取數(shù)據(jù)開(kāi)始
fetch next from stuCur --讀取當(dāng)前行的下一行,并使其置為當(dāng)前行(剛開(kāi)始時(shí)游標(biāo)置于表頭的前一行,即若表是從0開(kāi)始的,游標(biāo)最初置于-1處,所以第一次讀取的是頭一行)
fetch prior from stuCur --讀取當(dāng)前行的前一行,并使其置為當(dāng)前行
fetch first from stuCur --讀取游標(biāo)的第一行,并使其置為當(dāng)前行(不能用于只進(jìn)游標(biāo))
fetch last from stuCur --讀取游標(biāo)的最后一行,并使其置為當(dāng)前行(不能用于只進(jìn)游標(biāo))
fetch absolute 2 from stuCur --讀取從游標(biāo)頭開(kāi)始向后的第2行,并將讀取的行作為新的行
fetch relative 3 from stuCur --讀取從當(dāng)前行開(kāi)始向后的第3行,并將讀取的行作為新的行
fetch relative-2 from stuCur --讀取當(dāng)前行的上兩行,并將讀取的行作為新的行
–讀取數(shù)據(jù)結(jié)束
GO
close stuCur
Go
deallocate stuCur
Go

復(fù)制代碼
全局變量 @@FETCH_STATUS

FETCH語(yǔ)句的執(zhí)行狀態(tài)保存在全局變量@@FETCH_STATUS中,其值為0表示上一個(gè)FETCH執(zhí)行成功;為-1表示所要讀取的行不在結(jié)果集中;為-2表示被提取的行已不存在(已被刪除)。

4、關(guān)閉游標(biāo)(CLOSE)
語(yǔ)法
CLOSE { { [ GLOBAL ] cursor_name } | cursor_variable_name }
示例
close stuCur --若該游標(biāo)事先聲明并已打開(kāi)
Go

5、刪除游標(biāo)(DEALLOCATE)
對(duì)游標(biāo)進(jìn)行操作的語(yǔ)句使用游標(biāo)名稱(chēng)或游標(biāo)變量引用游標(biāo)。DEALLOCATE 刪除游標(biāo)與游標(biāo)名稱(chēng)或游標(biāo)變量之間的關(guān)聯(lián)。如果一個(gè)名稱(chēng)或變量是最后引用游標(biāo)的名稱(chēng)或變量,則將釋放游標(biāo),游標(biāo)使用的任何資源也隨之釋放。用于保護(hù)提取隔離的滾動(dòng)鎖在 DEALLOCATE 上釋放。用于保護(hù)更新(包括通過(guò)游標(biāo)進(jìn)行的定位更新)的事務(wù)鎖一直到事務(wù)結(jié)束才釋放。

語(yǔ)法
DEALLOCATE { { [ GLOBAL ] cursor_name } | @cursor_variable_name }
示例
游標(biāo)變量使用下列兩種方法之一與游標(biāo)關(guān)聯(lián):

復(fù)制代碼
–聲明一個(gè)游標(biāo)
declare abc cursor scroll
for
select * from XSB

–(1)通過(guò)名稱(chēng),使用set語(yǔ)句將游標(biāo)設(shè)置為游標(biāo)變量
declare @mycur cursor
set @mycur = abc

–(2)也可以不定義游標(biāo)名稱(chēng)而創(chuàng)建游標(biāo)并將其與變量關(guān)聯(lián)
declare @mycursor cursor
set @mycursor = cursor local scroll for
Select * from XSB
復(fù)制代碼
DEALLOCATE @cursor_variable_name 語(yǔ)句只刪除對(duì)游標(biāo)名稱(chēng)變量的引用。直到批處理、存儲(chǔ)過(guò)程或觸發(fā)器結(jié)束時(shí)變量離開(kāi)作用域,才釋放變量。在 DEALLOCATE @cursor_variable_name 語(yǔ)句之后,可以使用 SET 語(yǔ)句將變量與另一個(gè)游標(biāo)關(guān)聯(lián)。游標(biāo)可以理解為指針。

復(fù)制代碼
declare @mycur cursor
set @mycur = cursor local scroll for
select * from XSB

deallocate @mycur

set @mycur = cursor local scroll for
select * from XSB
GO
–不必顯式釋放游標(biāo)變量。變量在離開(kāi)作用域時(shí)被隱式釋放。
復(fù)制代碼
以下腳本顯示游標(biāo)如何持續(xù)到最后的名稱(chēng)或持續(xù)到引用它們的變量已釋放。

復(fù)制代碼
USE AdventureWorks2008R2;
GO
– Create and open a global named cursor that
– is visible outside the batch.
DECLARE abc CURSOR GLOBAL SCROLL FOR
SELECT * FROM Sales.SalesPerson;
OPEN abc;
GO
– Reference the named cursor with a cursor variable.
DECLARE @MyCrsrRef1 CURSOR;
SET @MyCrsrRef1 = abc;
– Now deallocate the cursor reference.
DEALLOCATE @MyCrsrRef1;
– Cursor abc still exists.
FETCH NEXT FROM abc;
GO
– Reference the named cursor again.
DECLARE @MyCrsrRef2 CURSOR;
SET @MyCrsrRef2 = abc;
– Now deallocate cursor name abc.
DEALLOCATE abc;
– Cursor still exists, referenced by @MyCrsrRef2.
FETCH NEXT FROM @MyCrsrRef2;
– Cursor finally is deallocated when last referencing
– variable goes out of scope at the end of the batch.
GO
– Create an unnamed cursor.
DECLARE @MyCursor CURSOR;
SET @MyCursor = CURSOR LOCAL SCROLL FOR
SELECT * FROM Sales.SalesTerritory;
– The following statement deallocates the cursor
– because no other variables reference it.
DEALLOCATE @MyCursor;
GO
復(fù)制代碼
三、用到的數(shù)據(jù)
1、創(chuàng)建表的腳本
復(fù)制代碼
CREATE TABLE [dbo].[XSB](
[學(xué)號(hào)] char NOT NULL,
[姓名] char NOT NULL,
[性別] [bit] NULL,
[出生時(shí)間] [date] NULL,
[專(zhuān)業(yè)] char NULL,
[總學(xué)分] [int] NULL,
[備注] varchar NULL,
PRIMARY KEY CLUSTERED
(
[學(xué)號(hào)] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
復(fù)制代碼
2、插入數(shù)據(jù)
復(fù)制代碼
insert into XSB values
(‘081101’,‘王林’,‘true’,‘1990-2-10’,‘計(jì)算機(jī)’,50,null),
(‘081102’,‘陳平’,‘true’,‘1991-2-1’,‘計(jì)算機(jī)’,50,null),
(‘081103’,‘王燕’,‘false’,‘1989-10-6’,‘計(jì)算機(jī)’,50,null),
(‘081104’,‘韋嚴(yán)平’,‘true’,‘1990-8-26’,‘計(jì)算機(jī)’,50,null),
(‘081106’,‘李芳芳’,‘true’,‘1990-11-20’,‘計(jì)算機(jī)’,50,null),
(‘081107’,‘李明’,‘true’,‘1990-5-1’,‘計(jì)算機(jī)’,54,‘已提前修完數(shù)據(jù)結(jié)構(gòu),并獲學(xué)分’),
(‘081108’,‘林一凡’,‘true’,‘1989-8-5’,‘計(jì)算機(jī)’,52,‘已提前修完一門(mén)課’),
(‘081109’,‘張強(qiáng)民’,‘true’,‘1989-8-11’,‘計(jì)算機(jī)’,50,null),
(‘081110’,‘張蔚’,‘false’,‘1991-7-22’,‘計(jì)算機(jī)’,50,‘三好生’),
(‘081111’,‘趙琳’,‘false’,‘1989-10-6’,‘計(jì)算機(jī)’,50,null),
(‘081113’,‘嚴(yán)紅’,‘false’,‘1989-8-11’,‘計(jì)算機(jī)’,48,‘一門(mén)不及格,待補(bǔ)考’),
(‘081201’,‘王敏’,‘true’,‘1989-6-10’,‘通信工程’,42,null),
(‘081202’,‘王林’,‘true’,‘1989-6-10’,‘通信工程’,40,‘一門(mén)不及格,待補(bǔ)考’)
GO
復(fù)制代碼

總結(jié)

以上是生活随笔為你收集整理的SQLServer游标详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。