SQLServer游标详解
一、游标概念
我们知道,关系数据库所有的关系运算其实是集合与集合的运算,它的输入是集合输出同样是集合,有时需要对结果集逐行进行处理,这时就需要用到游标。我们对游标的使用一本遵循“五步法”:声明游标—>打开游标—>读取数据—>关闭游标—>删除游标。以下就从这五步对游标的使用进行说明,并给出具体实例。
二、“五步法”讲解
1、声明游标(DECLARE CURSOR)
(1) DECLARE CURSOR 既接受基于 ISO 标准的语法,也接受使用一组 Transact-SQL 扩展的语法。
ISO 语法
DECLARE cursor_name [ INSENSITIVE ] [ SCROLL ] CURSOR
FOR select_statement
[ FOR { READ ONLY | UPDATE [ OF column_name [ ,...n ] ] } ]
[;] Transact-SQL 扩展语法
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] (说明游标的“作用域”)
[ FORWARD_ONLY | SCROLL ] (说明游标的“方向”)
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] (“说明游标的“类型”)
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
[ TYPE_WARNING ]
FOR select_statement
[ FOR UPDATE [ OF column_name [ ,...n ] ] ]
[;]
下面只对“T-SQL扩展语法”进行介绍,主要游标介绍作用域、方向及类型
(2)游标的作用域
LOCAL
说明所声明的游标为局部的,其作用域为创建它的批处理、存储过程或触发器,即在批处理、调用它的存储过程或触发器执行完成后,该游标被系统隐式释放。但,若游标作为存储过程OUTPUT 的输出参数,在存储过程终止后给游标变量分配参数可以继续引用游标,如果 OUTPUT 参数将游标传递回来,则游标在最后引用它的变量释放或离开作用域时释放。
GLOBAL
指定该游标的作用域对来说连接是全局的。在由连接执行的任何存储过程或批处理中,都可以引用该游标名称。该游标仅在断开连接时隐式释放。
注意:如果 GLOBAL 和 LOCAL 参数都未指定,则默认值由 default to local cursor 数据库选项的设置控制。在 SQL Server 7.0 版中,该选项默认为 FALSE,以便与 SQL Server 的早期版本匹配,在早期版本中,所有游标都是全局的。
declare testcur cursor --声明时未指定"local"或"global"关键字,系统默认游标是"global(全局)"的.
for
select 学号,姓名 from XSB
GO
open testcur
fetch next from testcur
GO
--------------------------------------------
declare testcur cursor local --声明时指定"local"关键字
for
select 学号,姓名 from XSB
open testcur
fetch next from testcur
GO --在这个批处理结束后,游标自动释放,即失效
-----------------------------------------------
declare testcur1 cursor local --声明时指定"local"关键字
for
select 学号,姓名 from XSB
GO --在这个批处理后,游标就失效了,后面对游标操作时,提示"名为 'testcur1' 的游标不存在"错误.
open testcur1
fetch next from testcur1
GO
(3)游标方向
FORWARD_ONLY
指定游标只能从第一行滚动到最后一行。FETCH NEXT 是唯一支持的提取选项。如果在指定 FORWARD_ONLY 时不指定 STATIC、KEYSET 和 DYNAMIC 关键字,则游标作为 DYNAMIC 游标进行操作。如果 FORWARD_ONLY 和 SCROLL 均未指定,则除非指定 STATIC、KEYSET 或 DYNAMIC 关键字,否则默认为 FORWARD_ONLY。STATIC、KEYSET 和 DYNAMIC 游标默认为 SCROLL。与 ODBC 和 ADO 这类数据库 API 不同,STATIC、KEYSET 和 DYNAMIC Transact-SQL 游标支持 FORWARD_ONLY。
SCROLL
指定所有的提取选项(FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE)均可用。如果未在 ISO DECLARE CURSOR 中指定 SCROLL,则 NEXT 是唯一支持的提取选项。如果也指定了 FAST_FORWARD,则不能指定 SCROLL。
declare directionCur cursor --不指定移动方向,则默认为“forward_only”
for
select 学号,姓名 from XSB
Go
open directionCur
fetch next from directionCur
Go
fetch prior from directionCur --错误“提取类型 prior 不能与只进游标一起使用。”
Go
close directionCur2
deallocate directionCur2
Go
-----------------------------------------
declare directionCur1 cursor forward_only --指定“forward_only”方向
for
select 学号,姓名 from XSB
Go
open directionCur1
fetch next from directionCur1
Go
fetch prior from directionCur1 --错误“提取类型 prior 不能与只进游标一起使用。”
Go
close directionCur2
deallocate directionCur2
Go
-----------------------------------------
declare directionCur2 cursor scroll --指定“scroll”方向
for
select 学号,姓名 from XSB
Go
open directionCur2
fetch next from directionCur2
Go
fetch prior from directionCur2
Go
close directionCur2
deallocate directionCur2
Go
---------------------------------
--结论:若游标没有指定任何访问或类型参数,则默认为全局、只进、动态游标。(这是在SQLServer2008 R2上的测试结果,具体取决于软件设置) --"scroll"和"fast_forward"不能一起使用
declare forwardTest cursor scroll fast_forward --报错“游标选项 SCROLL 和 FAST_FORWARD 冲突。”
for
select 学号,姓名 from XSB
Go --在 SQL Server 2000 中,FAST_FORWARD 和 FORWARD_ONLY 游标选项是互相排斥的。如果指定了二者,则会引发错误。
--在 SQL Server 2005 及更高版本中,这两个关键字可以用在同一个 DECLARE CURSOR 语句中。
declare forwardTest1 cursor forward_only fast_forward
for
select * from XSB
Go
(4)游标类型
STATIC
定义一个游标,以创建将由该游标使用的数据的临时复本。对游标的所有请求都从 tempdb 中的这一临时表中得到应答;因此,在对该游标进行提取操作时返回的数据中不反映对基表所做的修改,并且该游标不允许修改。及该游标是只读的。
KEYSET
指定当游标打开时,游标中行的成员身份和顺序已经固定。对行进行唯一标识的键集内置在 tempdb 内一个称为 keyset 的表中。
DYNAMIC
定义一个游标,以反映在滚动游标时对结果集内的各行所做的所有数据更改。行的数据值、顺序和成员身份在每次提取时都会更改。
FAST_FORWARD
指定启用了性能优化的 FORWARD_ONLY、READ_ONLY 游标。如果指定了 SCROLL 或 FOR_UPDATE,则不能也指定 FAST_FORWARD。
2、打开游标(OPEN)
语法
OPEN { { [ GLOBAL ] cursor_name } | cursor_variable_name }
示例
--打开游标并读取所有行
declare XSBcur cursor --声明
for
Select * from XSB
Go
open XSBcur --打开
fetch next from XSBcur --获取数据
while @@FETCH_STATUS = 0
begin
fetch next from XSBcur
end
close XSBcur --关闭
deallocate XSBcur --删除
全局变量 @@CURSOR_ROWS
该变量保存着最后打开的游标中的数据行数,当其值为0时,表示没有游标打开;其值为-1时,表示游标为动态的;当其值为-m(m为正整数)时,游标采用异步方式填充,m为当前键集中已填充的
行数;当其值为m(m为正整数)时,游标已被完全填充,m是游标中的数据行数。
3、读取数据
语法
FETCH
[ [ NEXT | PRIOR | FIRST | LAST
| ABSOLUTE { n | @nvar }
| RELATIVE { n | @nvar }
]
FROM
]
{ { [ GLOBAL ] cursor_name } | @cursor_variable_name }
[ INTO @variable_name [ ,...n ] ] --into说明将读取的游标数据存放到指定的变量中
示例
-----------------------------------
declare stuCur cursor scroll
for
select 学号,姓名 from XSB
GO
open stuCur
Go
--读取数据开始
fetch next from stuCur --读取当前行的下一行,并使其置为当前行(刚开始时游标置于表头的前一行,即若表是从0开始的,游标最初置于-1处,所以第一次读取的是头一行)
fetch prior from stuCur --读取当前行的前一行,并使其置为当前行
fetch first from stuCur --读取游标的第一行,并使其置为当前行(不能用于只进游标)
fetch last from stuCur --读取游标的最后一行,并使其置为当前行(不能用于只进游标)
fetch absolute 2 from stuCur --读取从游标头开始向后的第2行,并将读取的行作为新的行
fetch relative 3 from stuCur --读取从当前行开始向后的第3行,并将读取的行作为新的行
fetch relative-2 from stuCur --读取当前行的上两行,并将读取的行作为新的行
--读取数据结束
GO
close stuCur
Go
deallocate stuCur
Go
---------------------------
全局变量 @@FETCH_STATUS
FETCH语句的执行状态保存在全局变量@@FETCH_STATUS中,其值为0表示上一个FETCH执行成功;为-1表示所要读取的行不在结果集中;为-2表示被提取的行已不存在(已被删除)。
4、关闭游标(CLOSE)
语法
CLOSE { { [ GLOBAL ] cursor_name } | cursor_variable_name }
示例
close stuCur --若该游标事先声明并已打开
Go
5、删除游标(DEALLOCATE)
对游标进行操作的语句使用游标名称或游标变量引用游标。DEALLOCATE 删除游标与游标名称或游标变量之间的关联。如果一个名称或变量是最后引用游标的名称或变量,则将释放游标,游标使用的任何资源也随之释放。用于保护提取隔离的滚动锁在 DEALLOCATE 上释放。用于保护更新(包括通过游标进行的定位更新)的事务锁一直到事务结束才释放。
语法
DEALLOCATE { { [ GLOBAL ] cursor_name } | @cursor_variable_name }
示例
游标变量使用下列两种方法之一与游标关联:
--声明一个游标
declare abc cursor scroll
for
select * from XSB --(1)通过名称,使用set语句将游标设置为游标变量
declare @mycur cursor
set @mycur = abc --(2)也可以不定义游标名称而创建游标并将其与变量关联
declare @mycursor cursor
set @mycursor = cursor local scroll for
Select * from XSB
DEALLOCATE @cursor_variable_name 语句只删除对游标名称变量的引用。直到批处理、存储过程或触发器结束时变量离开作用域,才释放变量。在 DEALLOCATE @cursor_variable_name 语句之后,可以使用 SET 语句将变量与另一个游标关联。游标可以理解为指针。
declare @mycur cursor
set @mycur = cursor local scroll for
select * from XSB deallocate @mycur set @mycur = cursor local scroll for
select * from XSB
GO
--不必显式释放游标变量。变量在离开作用域时被隐式释放。
以下脚本显示游标如何持续到最后的名称或持续到引用它们的变量已释放。
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
三、用到的数据
1、创建表的脚本
CREATE TABLE [dbo].[XSB](
[学号] [char](6) NOT NULL,
[姓名] [char](8) NOT NULL,
[性别] [bit] NULL,
[出生时间] [date] NULL,
[专业] [char](12) NULL,
[总学分] [int] NULL,
[备注] [varchar](500) NULL,
PRIMARY KEY CLUSTERED
(
[学号] 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
2、插入数据
insert into XSB values
('','王林','true','1990-2-10','计算机',50,null),
('','陈平','true','1991-2-1','计算机',50,null),
('','王燕','false','1989-10-6','计算机',50,null),
('','韦严平','true','1990-8-26','计算机',50,null),
('','李芳芳','true','1990-11-20','计算机',50,null),
('','李明','true','1990-5-1','计算机',54,'已提前修完数据结构,并获学分'),
('','林一凡','true','1989-8-5','计算机',52,'已提前修完一门课'),
('','张强民','true','1989-8-11','计算机',50,null),
('','张蔚','false','1991-7-22','计算机',50,'三好生'),
('','赵琳','false','1989-10-6','计算机',50,null),
('','严红','false','1989-8-11','计算机',48,'一门不及格,待补考'),
('','王敏','true','1989-6-10','通信工程',42,null),
('','王林','true','1989-6-10','通信工程',40,'一门不及格,待补考')
GO
四、参考资料
http://technet.microsoft.com/zh-cn/library/ms181441(v=sql.105).aspx
SQLServer游标详解的更多相关文章
- SQLServer 游标详解
一.用到的数据 CREATE TABLE [dbo].[XSB]( ) NOT NULL, ) NOT NULL, [性别] [bit] NULL, [出生时间] [date] NULL, ) NUL ...
- SqlServer存储过程详解
SqlServer存储过程详解 1.创建存储过程的基本语法模板: if (exists (select * from sys.objects where name = 'pro_name')) dro ...
- Mysql高手系列 - 第19篇:mysql游标详解,此技能可用于救火
Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 这是Mysql系列第19篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符 ...
- Oracle游标详解大全
本文出自: http://www.cnblogs.com/sc-xx/archive/2011/12/03/2275084.html -- 声明游标:CURSOR cursor_name IS sel ...
- Oracle学习笔记之游标详解
游标 游标存在意义:解决"select *"返回空.多行记录问题,但凡select,就可能多行结果集,也就需要用游标. 游标分4步走:cursor.open.fetch.close ...
- PL/SQL游标详解
刚打开游标的时候,是位于一个空行,要用fetch into 才能到第一行. 只是要注意用更新游标的时候,不能在游标期间commit. 否则会报ORA-01002: fetch out of seque ...
- 第12章:MongoDB-CRUD操作--文档--查询--游标详解
①是什么游标 游标不是查询结果,可以理解为数据在遍历过程中的内部指针,其返回的是一个资源,或者说数据读取接口. 客户端通过对游标进行一些设置就能对查询结果进行有效地控制,如可以限制查询得到的结果数量. ...
- SQLServer 存储过程详解
Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...
- oracle --游标详解(转)
转自:http://blog.csdn.net/liyong199012/article/details/8948952 游标的概念: 游标是SQL的一个内存工作区,由系统或用户以变量的形式定 ...
随机推荐
- Js Json 互转
推荐: //js对象转换为 JSON 文本 var text = '[{"id":1,"name":"C","size" ...
- 触控(Touch)
1 使用触控实现一个简易的画板 1.1 问题 触控(Touch)是一个UITouch类型的对象,当用户触摸了屏幕上的视图时自动被创建,通常使用触控实现绘图.涂鸦.手写等功能.本案例使用触控实现一个简易 ...
- swift——设置navigationitemtitle的内容以及格颜色
1.用UILabel,自定义整个titleview // var TitleText = UILabel() self.TitleText.frame = CGRectMake(0, 0, 100, ...
- HBase配置&启动脚本分析
本文档基于hbase-0.96.1.1-cdh5.0.2,对HBase配置&启动脚本进行分析 date:2016/8/4 author:wangxl HBase配置&启动脚本分析 剔除 ...
- (转) Friendship and inheritance
原地址: http://www.cplusplus.com/doc/tutorial/inheritance/ Friend functions In principle, private and p ...
- Autorelease Pool-自动释放池
Autorelease Pool是Objective-C中的内存管理方式之一,它与线程和NSAutorelease类有关.每一个线程都拥有自己的Autorelease Pool栈,这个栈底层是由双向链 ...
- java学会需要掌握的知识(来源网上。。)
Java就业指导 2016-03-22 骆昊 程序人生 点击上方"程序人生"关注我们 想要成为合格的Java程序员或工程师到底需要具备哪些专业技能,面试者在面试之前到底需要准备哪些 ...
- html5本地存储web storage的简单使用
html5的一个非常cool的功能,就是web storage,类似于之前的cookie,不过与之不同的是,web storage 拥有本地5兆的容量可以存储,而cookie却只有4K,这是完全不能比 ...
- debian安装缺少网卡驱动rtl_nic/rtl8168e-2.fw和bcm43xx-0.fw
最近拿了公司一台旧笔记本来装debian玩,刻好盘之后安装,发现网卡驱动都无法装上. 这是因为这些网卡驱动不是开源的,顽固的debian便将他们从驱动列表中移除了... 我从debian官方找到了这两 ...
- 用git提交代码步骤
1.git add XXXX2.git commit - 'xxx'3.git stash4. //git pull --rebase 4. git rebase origin/develop git ...