一、用到的数据

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
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

二、游标概念

我们知道,关系数据库所有的关系运算其实是集合与集合的运算,它的输入是集合输出同样是集合,有时需要对结果集逐行进行处理,这时就需要用到游标。我们对游标的使用一本遵循“五步法”:声明游标—>打开游标—>读取数据—>关闭游标—>删除游标。以下就从这五步对游标的使用进行说明,并给出具体实例。

三、“五步法”讲解

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
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
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 --若该游标事先声明并已打开

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
--不必显式释放游标变量。变量在离开作用域时被隐式释放。

以下脚本显示游标如何持续到最后的名称或持续到引用它们的变量已释放。

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

SQLServer 游标详解的更多相关文章

  1. SQLServer游标详解

    一.游标概念 我们知道,关系数据库所有的关系运算其实是集合与集合的运算,它的输入是集合输出同样是集合,有时需要对结果集逐行进行处理,这时就需要用到游标.我们对游标的使用一本遵循“五步法”:声明游标—& ...

  2. SqlServer存储过程详解

    SqlServer存储过程详解 1.创建存储过程的基本语法模板: if (exists (select * from sys.objects where name = 'pro_name')) dro ...

  3. Mysql高手系列 - 第19篇:mysql游标详解,此技能可用于救火

    Mysql系列的目标是:通过这个系列从入门到全面掌握一个高级开发所需要的全部技能. 这是Mysql系列第19篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符 ...

  4. Oracle游标详解大全

    本文出自: http://www.cnblogs.com/sc-xx/archive/2011/12/03/2275084.html -- 声明游标:CURSOR cursor_name IS sel ...

  5. Oracle学习笔记之游标详解

    游标 游标存在意义:解决"select *"返回空.多行记录问题,但凡select,就可能多行结果集,也就需要用游标. 游标分4步走:cursor.open.fetch.close ...

  6. PL/SQL游标详解

    刚打开游标的时候,是位于一个空行,要用fetch into 才能到第一行. 只是要注意用更新游标的时候,不能在游标期间commit. 否则会报ORA-01002: fetch out of seque ...

  7. 第12章:MongoDB-CRUD操作--文档--查询--游标详解

    ①是什么游标 游标不是查询结果,可以理解为数据在遍历过程中的内部指针,其返回的是一个资源,或者说数据读取接口. 客户端通过对游标进行一些设置就能对查询结果进行有效地控制,如可以限制查询得到的结果数量. ...

  8. SQLServer 存储过程详解

    Transact-SQL中的存储过程,非常类似于Java语言中的方法,它可以重复调用.当存储过程执行一次后,可以将语句缓存中,这样下次执行的时候直接使用缓存中的语句.这样就可以提高存储过程的性能. Ø ...

  9. oracle --游标详解(转)

    转自:http://blog.csdn.net/liyong199012/article/details/8948952 游标的概念:     游标是SQL的一个内存工作区,由系统或用户以变量的形式定 ...

随机推荐

  1. EOS搭建

    http://mp.weixin.qq.com/s/RcDFCFCWpMIIAshJMqkxxw ,地址实效,请关注公众号 一下引用,只是技术记录交流 目前来讲,学习任何EOS相关技术的资料都来自ht ...

  2. Nginx 如何限制响应速度

    在 location 里设置 location { set $limit_rate 1k; 表示每秒只响应1k的速度 }

  3. 创建iview框架的项目

    http://www.cnblogs.com/jf-67/p/8479176.html 在使用‘vue init webpack my-project’创建项目时,出现了错误 npm ERR! cod ...

  4. Codeforces Round #423 Div. 1

    A:暴力赋值即可,并查集维护下一个未被赋值的位置. #include<iostream> #include<cstdio> #include<cmath> #inc ...

  5. Vue——服务器上部署vue.js

    服务器版本 [root@izuf63g0jydq42k49eo7zcz ~]# uname -a Linux izuf63g0jydq42k49eo7zcz -.el7.x86_64 # SMP Tu ...

  6. 一个模拟——抢票部分功能的 简单版(主要实例化一下 Lock 的使用)

    """ 抢票! 多个用户在同时读写同一个数据 """ from multiprocessing import Process,Lock im ...

  7. CH0802 占卜DIY

    模拟 没怎么看题..直接deque模拟水过了.. 但是后来回过头看了下题意..如果再次拿到正面朝上的牌,应该是废操作..可能是数据太水了... #include <bits/stdc++.h&g ...

  8. 用递归方法判断字符串是否是回文(Recursion Palindrome Python)

    所谓回文字符串,就是一个字符串从左到右读和从右到左读是完全一样的.比如:"level" .“aaabbaaa”. "madam"."radar&quo ...

  9. requests简单应用

    requests发送get请求 无参数的get请求: response = requests.get(url='http://ws.webxml.com.cn/WebServices/WeatherW ...

  10. FAQ常见问题解答---搭建hubot

    1. [root@test160 ~]# npm install -g n npm ERR! Error: CERT_UNTRUSTED 证书不受信任的 解决办法: npm config set st ...