• 简析一下SQL Server里面Fast_Forword 和 SRROLL 的区别


    这次简单说说游标的分类。

    先看看通常游标的语法

    DECLARE cursor_name CURSOR 
      [ LOCAL :局部游标,仅在当前会话有效
    | GLOBAL : 全局游标,全局有效,可以
    ] [ FORWARD_ONLY :只能向前游标,读取游标时只能使用 Next 谓词
    | SCROLL :滚动游标,FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE 都可以使用
    ] [ STATIC :定义一个游标,以创建将由该游标使用的数据的临时复本。对游标的所有请求都从 tempdb 中的这一临时表中得到应答;
    | KEYSET :对基表中的非键值所做的更改(由游标所有者更改或由其他用户提交)可以在用户滚动游标时看到。其他用户执行的插入是不可见的(不能通过 Transact-SQL 服务器游标执行插入)。如果删除某一行,则在尝试提取该行时返回值为 -2 的 @@FETCH_STATUS。
    | DYNAMIC :定义一个游标,以反映在滚动游标时对结果集内的各行所做的所有数据更改。行的数据值、顺序和成员身份在每次提取时都会更改。动态游标不支持 ABSOLUTE 提取选项
    | FAST_FORWARD :指定启用了性能优化的 FORWARD_ONLY、READ_ONLY 游标。如果指定了 SCROLL 或 FOR_UPDATE,则不能也指定 FAST_FORWARD
    ] [ READ_ONLY :只读游标,不能对游标内容进行更改,不能使用 where current of 语句
    | SCROLL_LOCKS :指定通过游标进行的定位更新或删除一定会成功。将行读入游标时 SQL Server 将锁定这些行,以确保随后可对它们进行修改。
    | OPTIMISTIC :指定如果行自读入游标以来已得到更新,则通过游标进行的定位更新或定位删除不成功。当将行读入游标时,SQL Server 不锁定行

    ] [ TYPE_WARNING ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] :制定那些列可以进行更新,如果不填,则默认全部可以更新
    ]

    好了,抛完书包之后,现在问题来了,本人尽量图文并茂的描述每种类型的特点吧……_(:з」∠)_

    --------------------------------------------------------------我是分割线-----------------------------------------------------------------------------------------------------------------------------------------------
    测试表的结构
    CREATE TABLE [dbo].[Employee]
    (
    [ID] [int] NOT NULL IDENTITY(1, 1) primary key,
    [NAME] [nvarchar] (50)  NULL,
    [Name2] [varchar] (50)  NULL
    ) ON [PRIMARY]
    GO



    FORWARD_ONLY 和 SCROLL
    这两者在用的过程中还是比较好区别。一个只能前进,一个可以前滚翻后滚翻什么的。
    先看看
    FORWARD_ONLY
    DECLARE CR_CURSOR CURSOR FAST_FORWARD --这个游标,是一个只读游标而已哦~
    FOR
        SELECT  ID ,
                NAME
        FROM    dbo.Employee
        WHERE   ID >= 24    
    
    DECLARE @ID INT ,
        @Name NVARCHAR(50)    
    OPEN CR_CURSOR
    FETCH NEXT FROM CR_CURSOR INTO @ID, @Name
    WHILE @@FETCH_STATUS = 0 
        BEGIN
        --UPDATE dbo.Employee SET Name2 = @Name WHERE CURRENT OF CR_CURSOR  因为是只读游标,所以是不允许修改游标本身内容
            UPDATE  dbo.Employee
            SET     Name2 = @Name
            WHERE   ID = @ID
            FETCH NEXT FROM CR_CURSOR INTO @ID, @Name
        END
    
    CLOSE CR_CURSOR
    DEALLOCATE CR_CURSOR
        
    然后我们看看执行计划,这个就跟普通的即时查询时没有任何区别的,所以我猜测,假如在游标读取过程中,数据发生了变化,是可以获取出来的。下面我来验证一下

    1、在读取之前,我先温柔的删除Employee 表里面,ID = 25的记录 
    DELETE FROM dbo.Employee WHERE ID = 25
    

      2、然后在读取游标里面开启单步调试,读到ID = 24的节点

         

      3、然后在读下一个游标之前,我添加了一条数据

    SET IDENTITY_INSERT Employee ON
    INSERT INTO dbo.Employee
            (ID,NAME )
    VALUES  ( 25,N'我是插进来的小三')
    SET IDENTITY_INSERT Employee OFF

    然后继续F10前进 ~咦~~25出来了野~

    证明了,FORWARD_ONLY 这货是在游标向下滚动的时候即使获取数据的。所以能捕捉到新插入或删除的数据。


    大致是这样纸了,下面在看看
    SCROLL 

    DECLARE CR_CURSOR CURSOR SCROLL  --代码基本一致,只是换成了 SCROLL
    FOR
        SELECT  ID ,
                NAME
        FROM    dbo.Employee
        WHERE   ID >= 24    
    
    DECLARE @ID INT ,
        @Name NVARCHAR(50)    
    OPEN CR_CURSOR
    FETCH NEXT FROM CR_CURSOR INTO @ID, @Name
    WHILE @@FETCH_STATUS = 0 
        BEGIN
            UPDATE dbo.Employee SET Name2 = @Name WHERE CURRENT OF CR_CURSOR  --这句现在可以执行了
            FETCH NEXT FROM CR_CURSOR INTO @ID, @Name
        END
    
    CLOSE CR_CURSOR
    DEALLOCATE CR_CURSOR
     惯例先看看这个执行计划吧~


    可以看到有一个查询过程要把数据插入到 CWT_PrimaryKey 的临时表里面。那我猜想,如果在游标读取途中,外部有数据的增加,是获取不到的了,那如果更新和删除会怎么样呢?实验一下
    1、在读取之前,我还是先温柔的删除Employee 表里面,ID = 25的记录 
    
    
    DELETE FROM dbo.Employee WHERE ID = 25
    
    
    
    

     2、然后在读取游标里面开启单步调试,读到ID = 24的节点

         

      3、然后在读下一个游标之前,我添加了一条数据

    SET IDENTITY_INSERT Employee ON
    INSERT INTO dbo.Employee
            (ID,NAME )
    VALUES  ( 25,N'我是插进来的小三')
    SET IDENTITY_INSERT Employee OFF

     然后F10……ID25没有粗线_(:з」∠)_直接到26去了

    确实,外部新增了数据,是获取不到的。下面测一下修改和删除。

    1、然后在读取游标里面开启单步调试,读到ID = 24的节点

         

     2、修改ID是25的数据

         

    UPDATE dbo.Employee SET NAME = '我是修改了的ID25哦' WHERE ID = 25
    

    3、然后按F10继续走,是可以获取的哟~

      


    删除呢?
    重试一遍,在单步的过程中直接将 ID = 25的数据抹掉,然后就直接循环结束了~查了一下 @@Fetch_Status = -2 提取数据失败,当然啦……数据都被删除了。顺带一提,如果继续往下取,还是可以取到下一条数据的哟~
    ……图就不截了。。。


    然后在继续试下各种方式,再进行补充





















































  • 相关阅读:
    View Focus的处理过程及ViewGroup的mFocused字段分析
    Android按键事件处理流程 -- KeyEvent
    Android中将xml布局文件转化为View树的过程分析(下)-- LayoutInflater源码分析
    Android中将xml布局文件转化为View树的过程分析(上)
    IntentService源码分析
    Android源码分析之SharedPreferences
    进程间传递文件描述符
    Epoll在LT和ET模式下的读写方式
    gdb
    Android开发之漫漫长途 Fragment番外篇——TabLayout+ViewPager+Fragment
  • 原文地址:https://www.cnblogs.com/Gin-23333/p/4076398.html
Copyright © 2020-2023  润新知