首页 > 数据库 >【转】SQL SERVER 游标

【转】SQL SERVER 游标

时间:2023-05-26 09:55:24浏览次数:53  
标签:name 指定 游标 SERVER SQL FORWARD FETCH

@@SQL server 游标

 

 

游标(Cursor)是SQL Server的一种数据访问机制,它使得程序可以逐行处理数据,即允许用户访问单独的数据行,对每一行数据进行单独的处理。

一,创建游标对象

创建游标对象,注意不是游标变量,游标名称不需要带前导@:

复制代码 复制代码
DECLARE cursor_name CURSOR 
[ LOCAL | GLOBAL ] [ FORWARD_ONLY | SCROLL ] [ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] ] [;]
复制代码 复制代码

在创建游标时,需要配置游标的选项,从定义游标的语法中,可以看出,游标共有5个选项。

1,游标的作用域

LOCAL 和 GLOBAL用于定义游标对象的作用域,

  • LOCAL指定游标的作用域是本地,默认值是LOCAL。
  • GLOBAL指定游标的作用域是全局的。

GLOBAL游标的作用域是连接,由连接内的batch或存储过程中引用,GLOBAL 游标仅在连接断开时被释放。

2,游标滚动的方向

FORWARD_ONLY 和 SCROLL用于指定游标滚动的方向:

  • FORWARD_ONLY 指定游标只能向前移动,即只能从第一行滚动到最后一行。FETCH NEXT 语句是唯一受支持的提取方法。
  • SCROLL 指定游标可以向前或向后滚动,

默认情况下,游标是FORWARD_ONLY(仅向前游标),只向前滚动。注意,向前一行是指下一行,向后一行是指上一行。当设置游标为FORWARD_ONLY和DYNAMIC时,游标在处理当前行时会检测到所有更改,这意味着对数据提交的任何修改操作(INSERT,UPDATE和DELETE)都会影响到获取的数据集,进而影响到FETCH NEXT语句。由于游标无法向后滚动,在某一行之后,上N行的数据修改无法查看,但是可以通过fetch查看下N行的数据修改。

3,游标是否对数据的修改可见

STATIC 指定静态游标,静态游标始终是只读的,在第一次打开游标时,在tempdb上创建游标的完整结果集,从临时表来响应游标的查询操作,因此对基表的修改操作,不会影响游标的结果集。在游标关闭之前,游标的结果集保持不变。

DYNAMIC 指定静态游标,动态游标反映结果集中的所有修改操作。结果集中的行数据值、顺序和成员在每次提取时都会改变。所有用户做的全部UPDATE、INSERT和DELETE语句均通过游标可见。

FAST_FORWARD 指定启动了性能优化的FORWARD_ONLY、READ_ONLY游标。如果指定了SCROLL或FOR_UPDATE,则不能指定FAST_FORWARD。

KEYSET 指定游标按照键集来滚动,游标的结果集(result set)包含两部分:键+其他列,键用于唯一标识一行数据,这意味着键(key)是由唯一标识数据行的一列或多列构成的,键集(KyeSet)是指由一组键构成的集合。

在打开游标时,SQL Server在tempdb中创建临时表keyset,该表是只读的,游标的滚动是通过keyset来迭代的。因此,当游标打开时,行的顺序已经固定。在游标滚动时,按照键集对游标的结果集进行join,返回完整的一行数据。

获取由键集驱动的游标时:

  • 当一个数据行被删除时,其key仍然存在于临时表keyset中,但是不再存在于结果集(result set)中。对该key进行fetch操作,@@FETCH_STATUS返回 -2
  • 当插入一个新的数据行时,如果插入操作发生在游标作用域之外,那么插入的数据对当前游标不可见;如果插入操作发生在游标作用域之内,那么插入的数据存在于结果集的末尾。
  • 更新键值的操作,等价于先删除旧的数据行,再插入一个新的数据行。

4,游标是否只读,是否支持定位修改

READ_ONLY 指定游标是只读的,不能通过游标修改数据。

SCROLL_LOCKS 指定通过游标进行的定位更新或删除一定会成功,当把行读入游标时,SQL Server将锁定这些行,以确保随后可对它们进行修改,如果还指定了FAST_FORWARD或STATIC,则不能指定SCROLL_LOCKS。

OPTIMISTIC 指定当行被读入游标之后,如果数据行被修改了,那么通过游标进行的定位更新或定位删除不成功。

当将行读入游标后,SQL Server不锁定行,SQL Server 通过以下两种方式来检测数据行是否被修改:

  • SQL Server使用表的timestamp列值的比较结果来确定行在读入游标后是否发生了变化。
  • 如果基表不包含timestamp列,SQL Server使用列值得校验和来检测当前行得数据值是否被修改。

如果检测到该行被修改,那么尝试进行的定位更新或删除将失败。如果还指定了FAST_FORWARD,则不能指定OPTIMISTIC。

5,是否通过游标更新数据

FOR UPDATE [OF column_name [,...n]] 用于在游标中定义可以更新的列,如果提供了  [OF column_name [,...n]] 选项,那么仅允许修改列出的列。如果仅指定了FOR UPDATE子句,那么可以修改所有的列。

二,获取数据和获取的状态

通过FETCH命令来获取游标中的结果集,并把获取的一行数据的各列赋值给变量列表:

复制代码 复制代码
FETCH  [ NEXT | PRIOR | FIRST | LAST   
            | ABSOLUTE { n | @nvar }   
            | RELATIVE { n | @nvar }   
        ]   
FROM { { [ GLOBAL ] cursor_name } | @cursor_variable_name }   
[ INTO @variable_name [ ,...n ] ]  
复制代码 复制代码

在赋值时,变量列表 一 一 对应SELECT 子句的字段列表,FETCH 子句可以通过以下选项来设置获取一行数据的方向:

  • NEXT:表示获取下一行,
  • PRIOR:表示获取上一行,
  • FIRST:表示获取第一行,
  • LAST:表示获取最后一行
  • ABSOLUTE n:表示获取从第一行开始的第n行,n表示第n行的绝对位置,
  • RELATIVE n:表示获取从当前行开始的第n行,n表示第n行的相对位置,

获取数据行时,是否获取成功,可以通过全局变量@@FETCH_STATUS来检测,注意,全局变量的作用域是当前的连接:

@@FETCH_STATUS  

该全局变量返回当前连接中打开的任何游标发出的最后一个FETCH语句的状态,状态值是整数:

注意,由于@@FETCH_STATUS 用于检测当前连接上的所有游标对象的状态,在使用时,要谨慎。在执行FETCH语句后,必须立即对@@FETCH_STATUS进行测试,然后再对其他游标执行任何其他FETCH语句。

三,举个例子

下面的脚本,定义了一个静态的只读游标,演示了游标打开、遍历和关闭的全过程:

复制代码 复制代码
declare @v1 int 
declare @v2 int

declare cursor_name cursor 
    forward_only static read_only
for
select c1,c2 from table_name;

open cursor_name

fetch next from cursor_name 
into @v1, @v2

while @@fetch_status=0
begin
    -- do something

    fetch next from cursor_name 
    into @v1, @v2
end

close cursor_name
deallocate cursor_name
复制代码 复制代码

 转自作者悦光阴 

出处http://www.cnblogs.com/ljhdo/

 

参考文档:

DECLARE CURSOR (Transact-SQL)

SQL Server基础之游标

 

https://www.cnblogs.com/sound-of-wind-rain/p/16414975.html

标签:name,指定,游标,SERVER,SQL,FORWARD,FETCH
From: https://www.cnblogs.com/wl-blog/p/17433874.html

相关文章

  • SqlServer中使用Select语句给变量赋值的时候需要注意的一个问题
    @@sqlserverselect赋值  我们知道在SqlServer中可以用Select语句给变量赋值,比如如下语句就为int类型的变量@id赋值1declare@idint=-1;23select@id=idfrom4(5select1asid6unionall7select2asid8unionall9select3asid10)a......
  • MySQL-DQL
    准备测试表,先跟着执行下面的SQL#1.登录MySQL后#2.创建test_database数据库,不存在则创建createdatabaseifnotexiststest_database;#2.1.如果test_database库存在,可以根据自己意愿删除或换个名称dropdatabasetest_database;#删除test_database数据库#3.进入刚创建的库......
  • SqlServer select 赋值问题
    @@sqlserverselect赋值 --变量赋值正确,单个数据默认为变量declare@s1varchar(20)set@s1=(selectMAX(parked_id)fromparked)--变量赋值错误,多个数据默认为数据集declare@s2varchar(20)set@s2=(selectparked_idfromparked)————————————————版权......
  • Mysql数据库遇到的问题及解决办法
    1、1205-Lockwaittimeoutexceeded;tryrestartingtransaction该异常代表数据库中有进程锁住了,会导致后续对数据库的操作都无法执行,需要杀掉锁住的进程 解决办法:1)、SELECT*FROMinformation_schema.INNODB_TRX;执行后找到名为trx_mysql_thread_id的列。2)、杀掉列中的......
  • MySQL学习进阶篇Day1
    1.存储引擎1.1MySQL体系结构  1).连接层最上层是一些客户端和链接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提......
  • MyBatis源码之SqlSession的解读
    MyBatis源码之SqlSession的解读1、SqlSession的简单使用首先先说一下SqlSession是什么?SqlSession其实就是对JDBC中Connection的一个封装,简化了对数据库的操作。当你获取到一个SqlSession的时候其实就是获取到一个数据库连接,可以进行数据库操作,SqlSession顾名思义就是一次与数据......
  • 使用游标(什么是游标、如何使用游标)
    @@游标使用游标(什么是游标、如何使用游标)已知MySQL检索操作返回一组称为结果集的行。这组返回的行都是与SQL语句相匹配的行(零行或者多行)。使用简单的SQL语句,例如,没有办法得到第一行、下一行或前10行,也不存在每次一行地处理所有行的简单办法(相对于成批的处理它们)。有时,需要......
  • 【RocketMQ】NameServer总结
    NameServer是一个注册中心,提供服务注册和服务发现的功能。NameServer可以集群部署,集群中每个节点都是对等的关系(没有像ZooKeeper那样在集群中选举出一个Master节点),节点之间互不通信。服务注册Broker启动的时候会向所有的NameServer节点进行注册,注意这里是向集群中所有的NameServ......
  • oracle 包游标使用
    包游标即在包头声明部分定义游标头,即游标的定义,把实现部分留给包体来完成,调用时可以通过包来调用,这样方便共享游标,实际实现功能类似视图。示例包头定义createorreplacepackagemypackageiscursorcur_employee(deptnoinemployee.departmentno%type)return......
  • mysql之ddl之trancate
    截断,trancatetabletk_student即保留表结构,重新建表tk_student相比于delete这种dml,对数据操作(一条一条删除数据)的语句,效率要高很多。但delete也有优点,即可以回滚事务(反悔),而trancate(隐式提交)不能回滚(反悔)两种方法删除数据后,如果在添加语句,对于自增的变量(一般是主键),则delete......