zoukankan      html  css  js  c++  java
  • 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

    参考文档:

    DECLARE CURSOR (Transact-SQL)

    SQL Server基础之游标

  • 相关阅读:
    HTTP学习笔记(1)ULR语法
    wsdl地址如何在远程服务器上查看源码?
    java线程详解(三)
    java线程详解(二)
    java线程详解(一)
    java中this用法总结
    Linux运行python程序
    如何获取到Java对象的地址
    IDEA 远程调试
    linux环境中mysql默认端口3306无法连接问题排查
  • 原文地址:https://www.cnblogs.com/ljhdo/p/13502897.html
Copyright © 2011-2022 走看看