SQL sever2008中的游标

news2024/11/30 14:37:25

目录

一、游标概述

二、游标的实现

三、优缺点

3.1优点:

3.2缺点:

四、游标类型

4.1静态游标

4.2动态游标

4.3只进游标

4.4键集驱动游标

4.5显示游标:

4.6隐式游标

五、游标基本操作

5.1声明游标

5.1.1.IS0标准语法

5.1.1.1语法格式如下:

5.1.1.2示例应用:

5.1.2.Transact-.SQL扩展的语法

5.1.2.1语法格式如下:

5.1.2.2示例应用

5.2打开游标

5.2.1语法格式如下:

5.2.2示例应用:

5.3读取游标中数据

5.3.1语法格式如下:

5.3.2示例应用

5.4关闭游标

5.4.1语法格式如下:

5.4.2示例应用

5.5释放游标

5.5.1语法格式如下:

5.5.2示例应用

六、游标查看

6.1sp_cursor_list

6.1.1语法格式如下:

6.1.2示例应用

6.2sp_describe_cursor

6.2.1语法格式如下:

6.2.2示例应用

七、隐式与显示游标

7.1显示游标

7.1.1语法格式:

7.1.2示例应用

7.2隐式游标

7.2.1语法格式:

7.2.2示例应用


一、游标概述

          关系数据库中的操作会对整个行集起作用。由SELECT语句返回的行集包括满足该语句的WHERE子句中条件的所有行,这种由语句返回的完整行集称为结果集。应用程序,特别是交互式联机应用程序,并不总能将整个结果集作为一个单元来有效地处理。这些应用程序需要一种机制以便每次处理一行或一部分行,游标就是提供这种机制的对结果集的一种扩展。

游标通过以下方式来扩展结果处理:

  • 允许定位在结果集的特定行。
  • 从结果集的当前位置检索一行或一部分行。
  • 支持对结果集中当前位置的行进行数据修改。
  • 为由其他用户对显示在结果集中的数据库数据所作的更改提供不同级别的可见性支持。
  • 提供脚本、存储过程和触发器中用于访问结果集中的数据的Transact-SQL语句。

        游标(Cursor)是一种用于在 SQL Server 数据库中遍历查询结果集的机制。它允许逐行处理查询结果,类似于一个指针或迭代器,可以通过游标控制在结果集中移动。使用游标可以逐行处理数据,并提供更高级别的操作。

二、游标的实现

     游标提供了一种从表中检索数据并进行操作的灵活手段,游标主要用在服务器上,处理由客户端发送给服务器端的SQL语句,或是批处理、存储过程、触发器中的数据处理请求。游标的优点主要在于它可以定位到结果集中的某一行,并可以对该行数据执行特定操作,为用户在处理数据的过程中提供了很大方便。一个完整的游标是由5部分组成,并且这5个部分应符合下面的顺序:

  • (1)声明游标。
  • (2)打开游标。
  • (3)从一个游标中查找信息。
  • (4)关闭游标。
  • (5)释放游标。

三、优缺点

3.1优点:

  • 游标可以处理复杂的查询逻辑和业务流程,使得数据处理更加灵活。
  • 允许逐行处理查询结果集,对每一行进行特定的操作。允许对查询结果集进行自定义的操作、更新和删除。
  • 可以在结果集中进行随意导航和遍历。
  • 允许在不同的行之间跳跃,以满足特定需求。

3.2缺点:

  • 使用游标需要占用额外的资源和内存,在处理大型数据集时可能会导致性能问题。
  • 游标通常比集合操作的性能较差,因为它们需要逐行处理数据。
  • 错误的使用游标可能导致死锁或性能瓶颈。

四、游标类型

     SQL Server提供了4种类型的游标:静态游标、动态游标、只进游标和键集驱动游标。这些游标的检测结果集变化的能力和内存占用的情况都有所不同,数据源没有办法通知游标当前提取行的更改。游标检测这些变化的能力也受事务隔离级别的影响。

4.1静态游标

     静态游标的完整结果集在游标打开时建立在tempdb中。静态游标总是按照游标打开时的原样显示结果集。静态游标在滚动期间很少或根本检测不到变化,虽然它在tempdb中存储了整个游标,但消耗的资源很少。尽管动态游标使用tempdb的程度最低,在滚动期间它能够检测到所有变化,但消耗的资源也更多。键集驱动游标介于二者之间,它能检测到大部分的变化,但比动态游标消耗更少的资源。这意味着在游标打开时,它会被缓存,并且不会受到对源数据的更改的影响

4.2动态游标

     动态游标与静态游标相对。当滚动游标时,动态游标反映结果集中所作的所有更改。结果集中的行数据值、顺序和成员在每次提取时都会改变。所有用户做的全部UPDATE、NSERT和DELETE语句均通过游标可见。这意味着当使用动态游标时,结果集可能会发生变化

4.3只进游标

     只进游标不支持滚动,它只支持游标从头到尾顺序提取。只在从数据库中提取出来后才能进行检索。对所有由当前用户发出或由其他用户提交,并影响结果集中的行的NSERT、UPDATE和DELETE语句,其效果在这些行从游标中提取时是可见的。可以使用 FORWARD_ONLY 游标类型创建只进游标。

4.4键集驱动游标

     打开游标时,键集驱动游标中的成员和行顺序是固定的。键集驱动游标由一套被称为键集的唯一标识符(键)控制。键由以唯一方式在结果集中标识行的列构成。键集是游标打开时来自所有适合SELECT语句的行中的一系列键值,键集驱动游标的键集在游标打开时建立在tempdb中。对非键集列中的数据值所做的更改(由游标所有者更改或其他用户提交)在用户滚动游标时是可见的,在游标外对数据库所做的插入在游标内是不可见的,除非关闭并重新打开游标。

游标同样是可以分为显示游标(Explicit Cursor)和隐式游标(Implicit Cursor)。

4.5显示游标:

    显示游标是通过使用 DECLARE CURSOR 语句显式声明的游标。可以指定游标的名称、类型以及其他属性,例如数据访问方式、是否可滚动、是否只读等。显示游标需要手动控制其生命周期,包括打开、关闭和获取结果集中的行。详细用法查看第七节内容

4.6隐式游标

     隐式游标是在特定的 SQL 语句中隐含地创建的游标。它通常与 SELECT 语句一起使用,在执行SELECT语句时自动创建一个默认游标。即当查询返回结果集时,隐式游标会自动被创建和管理。隐式游标无需手动声明或控制,系统会自动处理游标的生命周期,并在需要时进行打开、遍历和关闭。 隐式声明游标是一种简单的方式,它这种方式在处理较简单的游标需求时比较方便。详细用法查看第七节内容

五、游标基本操作

5.1声明游标

     声明游标可以使用DECLARE CURSOR语句。此语句有两种语法声明格式,分别为ISO标准语法和Transact-.SQL扩展的语法。下面将分别介绍。

5.1.1.IS0标准语法

5.1.1.1语法格式如下:
DECLARE cursor_name [ INSENSITIVE ][ SCROLL ] CURSOR
FOR select_statement
FOR {READ ONLY | UPDATE [ OF column_name [,...n ]]}

参数说明:

  • DECLARE cursor_name:指定一个游标名称,其游标名称必须符合标识符规则。
  • NSENSITIVE:定义一个游标,以创建将由该游标使用的数据的临时副本。对游标的所有请求都从tempdb中的临时表中得到应答;因此,在对该游标进行提取操作时返回的数据中不反映对基表所作的修改,并且该游标不允许修改。使用SQL-92语法时,如果省略NSENSITIVE,(任何用户)对基表提交的删除和更新都反映在后面的提取中。
  • SCROLL:指定所有的提取选项(FIRST、LAST、PRIOR、NEXT、RELATIVE、ABSOLUTE)均可用。
  •       FRST:取第一行数据。
  •       LAST:取最后一行数据
  •       PRIOR:取前一行数据。
  •       NEXT:取后一行数据。
  •       RELATIVE:按相对位置取数据。
  •       ABSOLUTE:按绝对位置取数据。

如果未指定SCROLL,则NEXT是唯一支持的提取选项。

  • select_statement:定义游标结果集的标准SELECT语句。在游标声明的select statement内不允许使用关键字COMPUTE、COMPUTE BY、FOR BROWSE和NTO.
  • READ ONLY:表明不允许游标内的数据被更新,尽管在默认状态下游标是允许更新的。在UPDATE或DELETE语句的WHERE CURRENT OF子句中不允许引用游标。
  • UPDATE[OF column_name[,n]]:定义游标内可更新的列.如果指定OF column_name[,n]参数,则只允许修改所列出的列。如果在UPDATE中未指定列的列表,则可以更新所有列。 
5.1.1.2示例应用:

 以下是声明游标的部分示例:

EMP表数据:

【例1】创建一个名为Cur_Emp的标准游标。SQL语句如下:

USE test;
DECLARE Cur_Emp CURSOR FOR
SELECT * FROM Emp
Go

【例2】创建一个名为Cur_Emp01的只读游标。SQL语句如下:

USE test 
DECLARE Cur_Emp_01 CURSOR FOR
SELECT * FROM Emp
FOR READ ONLY --只读游标
Go

【例3】创建一个名为Cur_Emp_02的更新游标,默认更新所有列。SQL语句如下:

USE test
DECLARE Cur_Emp_02 CURSOR FOR
SELECT Ename,Eage,Esal FROM Emp
FOR UPDATE --更新游标
GO

【例4】创建一个名为Cur_Emp_03的更新游标,指定更新的列。SQL语句如下:

USE test
DECLARE Cur_Emp_03 CURSOR FOR
SELECT Ename,Eage,Esal FROM Emp
FOR UPDATE OF Ename --更新游标,允许对 Ename 列进行更新操作
GO

5.1.2.Transact-.SQL扩展的语法

5.1.2.1语法格式如下
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 ]]]

DECLARE CURSOR语句的参数及说明如下所示

  • DECLARE cursor_name:指定一个游标名称,其游标名称必须符合标识符规则;
  • LOCAL:定义游标的作用域仅限在其所在的批处理、存储过程或触发器中。当建立游标在存储过程执行结束后,游标会被自动释放;
  • GLOBAL:指定该游标的作用域对连接是全局的。在由连接执行的任何存储过程或批处理中,都可以引用该游标名称。该游标仅在脱接时隐性释放;
  • FORWARD_ONLY:指定游标只能从第一行滚动到最后一行。FETCH NEXT 是唯一受支持的提取选项,非指定STATIC、KEYSET 或DYNAMIC 关键字否则默认为 FORWARD_ONLY。STATIC、KEYSET 和DYNAMIC游标默认为 SCROLL。与ODBC 和ADO 这类数据库 API 不同,STATIC、KEYSET 和 DYNAMICTransact-SOL游标支持FORWARD_ONLY。FAST_FORWARD和FORWARD_ONLY 是互斥的,如果指定一个,则不能指定另一个;
  • STATIC:定义一个游标,以创建将由该游标使用的数据的临时副本。对游标的所有请求都从tempdb中的该临时表中得到应答:因此,在对该游标进行提取操作时返回的数据中不反映对基表所做的修改,并且该游标不允许修改;
  • KEYSET:指定当游标打开时,游标中行的成员资格和顺序已经固定。对行进行唯一标识的键集内置在tempdb内一个称为keyset的表中。对基表中的非键值所做的更改(由游标所有者更改或由其他用户提交)在用户滚动游标时是可视的。其他用户进行的插入是不可视的(不能通过Transact-SQL服务器游标进行插入)。如果某行已别除,则对该行的提取操作将返回@@FETCH STATUS值-2。从游标外更新键值类似于删除旧行后接着插入新行的操作。含有新值的行不可视,对含有旧值的行的提取操作将返回@@FETCH STATUS值-2。如果通过指定WHERE CURRENT OF子句用游标完成更新,则新值可视;
  • DYNAMIC:定义一个游标,以反映在滚动游标时对结果集内的行所做的所有数据的更改。行的数据值、顺序和成员在每次提取时都会更改。动态游标不支持ABSOLUTE提取选项;
  • FAST_FORWARD:指明一个FORWARD_ONLY、READ_ONLY型游标;
  • SCROLL_LOCKS:指定确保通过游标完成的定位更新或定位删除可以成功。将行读入游标以确保它们可用于以后的修改时,SQL Server会锁定这些行。如果还指定了FAST_FORWARD,则不能指定SCROLL_LOCKS;
  • OPTIMISTIC:指明在数据被读入游标后,如果游标中某行数据已发生变化,那么对游标数据进行更新或删除可能会导致失败;
  • TYPE_WARNING:指定如果游标从所请求的类型隐性转换为另一种类型,则给客户端发送警告消息;
5.1.2.2示例应用

以下是声明游标的部分示例:

【例1】局部只进只读游标

DECLARE cursor_name CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR SELECT column1, column2 FROM table_name;

示例声明一个局部的只进只读游标,它从 table_name 表中选择 column1column2 列,并且只能以向前遍历的方式访问结果集。 

【例2】全局可滚动可更新游标

DECLARE cursor_name CURSOR GLOBAL SCROLL 
FOR UPDATE OF column1, column2
FOR SELECT column1, column2 FROM table_name;

示例声明一个全局的可滚动游标,它从 table_name 表中选择 column1column2 列,并允许对这两列进行更新操作。 

【例3】静态只读游标

DECLARE cursor_name CURSOR STATIC READ_ONLY
FOR SELECT * FROM table_name;

示例声明一个静态只读游标,它从 table_name 表中选择所有列,并且只能以向前遍历的方式访问结果集。 

【例4】动态可滚动乐观锁游标

DECLARE cursor_name CURSOR DYNAMIC SCROLL OPTIMISTIC
FOR SELECT column1, column2 FROM table_name
FOR UPDATE OF column1;

示例声明一个动态可滚动乐观锁游标,它从 table_name 表中选择 column1column2 列,并且允许对 column1 列进行更新操作。 

【例5】局部快速向前仅警告游标

DECLARE cursor_name CURSOR LOCAL FAST_FORWARD TYPE_WARNING
FOR SELECT column1, column2 FROM table_name
FOR UPDATE OF column1, column2;

示例声明一个局部快速向前仅警告游标,它从 table_name 表中选择 column1column2 列,并且允许对这两列进行更新操作 .

【例6】静态可滚动游标

DECLARE cursor_name CURSOR STATIC SCROLL 
FOR SELECT column1, column2 FROM table_name;

示例声明一个静态可滚动游标,从 table_name 表中选择 column1column2 列。 

【例7】键集游标

DECLARE cursor_name CURSOR KEYSET 
FOR SELECT column1, column2 FROM table_name;

示例声明一个键集游标,从 table_name 表中选择 column1column2 列。键集游标在打开时获取结果集的键值,并根据这些键值定位结果集中的行。 

【例8】动态只进游标

DECLARE cursor_name CURSOR DYNAMIC FORWARD_ONLY 
FOR SELECT column1, column2 FROM table_name;

示例声明一个动态只进游标,从 table_name 表中选择 column1column2 列。动态只进游标每次都会重新执行查询,而不是缓存结果集。 

【例9】全局并发锁游标

DECLARE cursor_name CURSOR GLOBAL SCROLL SCROLL_LOCKS 
FOR SELECT column1, column2 FROM table_name;

示例声明一个全局并发锁游标,从 table_name 表中选择 column1column2 列。全局并发锁游标允许其他事务以共享或排他方式访问相同的数据行。 

【例10】局部快速向前仅警告游标

DECLARE cursor_name CURSOR LOCAL FAST_FORWARD TYPE_WARNING
FOR SELECT column1, column2 FROM table_name;

示例声明一个局部快速向前仅警告游标,从 table_name 表中选择 column1column2 列。该游标以快速向前的方式遍历结果集,但在某些情况下会生成警告消息。 

注意:

一定要根据自己的数据库结构和需求来编写适合的 SELECT 语句和游标名称。

同时,还应该根据具体情况调整是否需要 LOCAL 或 GLOBAL、FORWARD_ONLY 或 SCROLL、STATIC、KEYSET、DYNAMIC 或 FAST_FORWARD 等选项。

5.2打开游标

打开一个声明的游标可以使用OPEN命令。

5.2.1语法格式如下:

OPEN{{[GLOBAL ] cursor_name } | cursor_variable_name}

参数说明

  • GLOBAL:指定cursor name为全局游标。
  • cursor_name:已声明的游标名称,如果全局游标和局部游标都使用cursor name作为其名称,那么如果指定了GLOBAL,cursor name指的是全局游标,否则cursor name指的是局部游标。
  • cursor_variable_name:游标变量的名称,该名称引用一个游标。

说明:
如果使用NSENSITIV或STATIC选项声明了游标,那么OPEN将创建一个临时表以保留结果集。如果结果集中任意行的大小超过SQLServer表的最大行大小,OPEN将失败。如果使用
KEYSET选项声明了游标,那么OPEN将创建一个临时表以保留键集。临时表存储在tempdb中。

5.2.2示例应用:

【例1】首先声明一个名为Emp_01的游标,然后使用OPEN命令打开该游标。SQL语句如下:

USE test
DECLARE Emp_01 CURSOR FOR  --声明游标
SELECT * FROM Emp
WHERE ID ='1'
OPEN Emp_01 --打开游标
GO

5.3读取游标中数据

     当打开一个游标之后,就可以读取游标中的数据了。可以使用ETCH命令读取游标中的某一行数据。

5.3.1语法格式如下:

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

FETCH命令的参数及说明如下所示:

  • NEXT:返回紧跟当前行之后的结果行,并且当前行递增为结果行。如果FETCH NEXT为对游标
  • 的第一次提取操作,则返回结果集中的第一行。NEXT为默认的游标提取选项;
  • PRIOR:返回紧临当前行前面的结果行,并且当前行递减为结果行。如果FETCH PRIOR为对游
  • 标的第一次提取操作,则没有行返回并且游标置于第一行之前;
  • FIRST:返回游标中的第一行并将其作为当前行;
  • LAST:返回游标中的最后一行并将其作为当前行;
  • ABSOLUTE{ n |@nvar}:如果n或@nvar为正数,返回从游标头开始的第n行,并将返回的行变成新的当前行。如果n或@nvar为负数,返回游标尾之前的第n行,并将返回的行变成新的当前行。如果n或@nvar为O,则没有行返回;
  • RELATIVE (n |@nvar}:如果n或@nvar为正数,返回当前行之后的第n行,并将返回的行变成新的当前行。如果n或@nvar为负数,返回当前行之前的第n行,并将返回的行变成新的当前行。如果n或@nvar为O,返回当前行。如果对游标的第一次提取操作时将FETCHRELATIVE的n或@nvar指定为负数或O,则没有行返回。n必须为整型常量且@nvar必须为smallint、tinyint或int;
  • GLOBAL:指定cursor_name为全局游标;
  • cursor_name:要从中进行提取的开放游标的名称。如果同时以cursor_name作为名称的全局和局部游标存在,若指定为GLOBAL,则cursor_name对应于全局游标,未指定GLOBAL,则对应于局部游标;
  • @cursor_ariable_name:游标变量名,引用要进行提取操作的打开的游标;
  • INTO @variable name[,...n]:允许将提取操作的列数据放到局部变量中。列表中的各个变量从左到右与游标结果集中的相应列相关联。各变量的数据类型必须与相应的结果列的数据类型匹配或是结果列数据类型所支持的隐性转换。变量的数目必须与游标选择列表中的列的数目一致;
  • @@FETCH_STATUS:返回上次执行FETCH命令的状态。在每次用FETCH从游标中读取数据时,都应检查该变量,以确定上次FETCH操作是否成功,决定如何进行下一步处理。@@FETCH_STATUS变量有3个不同的返回值,说明如下:(1)返回值为O:FETCH语句成功:(2)返回值为-1:FETCH语句失败或此行不在结果集中:(3)返回值为-2:被提取的行不存在;

说明    

      在前两个参数中,包含了n和@nvar其表示游标相对与作为基准的数据行所偏离的位置。

      当使用SQL-92语法来声明一个游标时,没有选择SCROLL选项,则只能使用FETCH NEXT命令来从游标中读取数据,即只能从结果集第一行按顺序地每次读取一行。由于不能使用FIRST、LAST、PRIOR,所以无法回滚读取以前的数据。如果选择了SCROLL选项,则可以使用所有的FETCH操作。 

5.3.2示例应用

【例1】用@@FETCH_STATUS控制一个WHLE循环中的游标活动。SQL语句如下:

USE test
go
DECLARE Readcursor CURSOR FOR
SELECT * FROM emp
OPEN ReadCursor
FETCH NEXT FROM Readcursor
WHILE @@FETCH_STATUS=0 
BEGIN
    FETCH NEXT FROM ReadCursor
END

运行结果如图所示:从游标中读取数据

5.4关闭游标

     当游标使用完毕之后,使用CLOSE语句可以关闭游标,但不释放游标占用的系统资源。

5.4.1语法格式如下:

CLOSE{{[GLOBAL] cursor_name }|cursor_variable_name}

参数说明:

  • GLOBAL:指定cursor name为全局游标。
  • cursor_name:开放游标的名称。如果全局游标和局部游标都使用cursor name作为它们的名称,那么当指定GLOBAL时,cursor_name引用全局游标;否则cursor_name引用局部游标。
  • cursor_variable_name:与开放游标关联的游标变量名称。

5.4.2示例应用

【例1】声明一个名为CloseCursor的游标,并使用Close语句关闭游标,SQL语句如下:

USE test
DECLARE CloseCursor Cursor FOR
SELECT * FROM emp
FOR READ ONLY
OPEN CloseCursor
CLOSE CloseCursor

5.5释放游标

    当游标关闭之后,并没有在内存中释放所占用的系统资源,所以可以使用DEALLOCATE命令删
除游标引用。当释放最后的游标引用时,组成该游标的数据结构由SQL Server释放。

5.5.1语法格式如下:

DEALLOCATE{{[GLOBAL cursor_name @cursor_variable_name

参数说明:

  • cursor name:已声明游标的名称。当全局和局部游标都以cursor name作为它们的名称存在时,如果指定GLOBAL,则cursor name引用全局游标,如果未指定GLOBAL,则cursor name引用局部游标。
  • @cursor_variable_name:cursor变量的名称。@cursor variable name必须为cursor类型。

    当使用DEALLOCATE@cursor_variable_name来删除游标时,游标变量并不会被释放,除非超过使用该游标的存储过程和触发器的范围。

5.5.2示例应用

【例1】使用DEALLOCATE命令释放名为FreeCursor的游标。SQL语句如下:

USE test
DECLARE FreeCursor Cursor FOR
SELECT * FROM EMP
OPEN FreeCursor
Close FreeCursor
DEALLOCATE FreeCursor

六、游标查看

    创建游标后,通常使用sp_cursor_list和sp_describe_cursor查看游标的属性。sp_cursor_list用来报告当前为连接打开的服务器游标的属性,sp_describe_cursor用于报告服务器游标的属性。下面将详细介绍这两个系统过程。

6.1sp_cursor_list

sp_cursor_list报告当前为连接打开的服务器游标的属性。

6.1.1语法格式如下:

sp_cursor_list [@cursor_return =]cursor_variable_name OUTPUT,[@cursor_scope =]cursor_scope

参数说明

  • [@cursor_return=]cursor_variable_name OUTPUT:已声明的游标变量的名称。cursor_variable_name的数据类型为cursor,无默认值。游标是只读的可滚动动态游标。
  • [@cursor_scope=]cursor_scope:指定要报告的游标级别。cursor_scope的数据类型为int,无默认值,可取值如下表所示。
cursor_scope可取值
说明
1报告所有本地游标
2报告所有全局游标
3

报告本地游标和全局游标 

6.1.2示例应用

【例1】声明一个游标,并使用sp_cursor_Iist报告该游标的属性,SQL语句如下:

USE test 
GO
DECLARE Cur_Emp CURSOR FOR
SELECT EName
FROM Emp
WHERE EName LIKE'李%'
OPEN Cur_Emp
DECLARE @Report CURSOR
EXEC master.dbo.sp_cursor_list @cursor_return=@Report OUTPUT,
       @cursor_scope =2
FETCH NEXT from @Report
WHILE(@@FETCH_STATUS <>-1)
BEGIN
  FETCH NEXT from @Report
END
CLOSE @Report
DEALLOCATE @Report
GO
CLOSE Cur_Emp
DEALLOCATE Cur_Emp
GO

执行结果如下:

6.2sp_describe_cursor

sp_describe_cursor用于报告服务器游标的属性。

6.2.1语法格式如下:

sp_describe_cursor[@cursor_return =]output_cursor_variable OUTPUT
   {[,[@cursor_source=]N'local'
   ,[@cursor_identity =N'local_cursor_name']
   |[,[@cursor_source =]N'global'
  ,[@cursor_identity =]N'global_cursor_name']
  |[,[@cursor_source =]N'variable'
    ,[@cursor_identity =]N'input_cursor_variable']
    }

sp_describe_cursor语句的参数及说明如下所示:

  • [@cursor return=]output_cursor_variable OUTPUT :用于接收游标输出的声明游标变量的名称。output_cursor_)variable的数据类型为cursor,无默认值。调用sp_describe_cursor时,该参数不得与任何游标关联。返回的游标是可滚动的动态只读游标;
  • [,[@cursor_source=]N'local' |N'global' | N'variable'}:指定是使用局部游标的名称、全局游标的名称还是游标变量的名称来指定要报告的游标。该参数的类型为nvarchar(30);
  • [@cursor_identity =N'local_cursor_name']:由具有LOCAL关键字或默认设置为LOCAL的DECLARE CURSOR语句创建的游标名称。local_cursor_name的数据类型为nvarchar(128);
  • [@cursor_identity =]N'global_cursor_name']:由具有GLOBAL关键字或默认设置为GLOBAL的DECLARE CURSOR语句创建的游标名称。global_cursor_name的数据类型为nvarchar(l28);
  • [@cursor_identity =]N'input_cursor_variable']:与所打开游标相关联的游标变量的名称。input_cursor_variable的数据类型为nvarchar(128);

6.2.2示例应用

【例1】声明一个游标,并使用sp_describe_cursor报告该游标的属性。SQL语句如下:

USE test 
GO
DECLARE Cur_Emp CURSOR STATIC FOR
SELECT EName
FROM Emp
OPEN Cur_Emp
DECLARE @Report CURSOR
EXEC master.dbo.sp_describe_cursor @cursor_return= @Report OUTPUT,
       @cursor_source= N'global',@cursor_identity =N'Cur_Emp'
FETCH NEXT from @Report
WHILE(@@FETCH_STATUS<>-1)
BEGIN
  FETCH NEXT from @Report
END

CLOSE @Report
DEALLOCATE @Report
GO
CLOSE Cur_Emp
DEALLOCATE Cur_Emp
GO

执行结果如下:

七、隐式与显示游标

7.1显示游标

   显式声明游标允许我们为游标设置更多的选项和参数以满足特定的需求,但它需要更多的代码。

7.1.1语法格式:

--1. 声明游标:
DECLARE cursor_name CURSOR [LOCAL | GLOBAL] [FORWARD_ONLY | SCROLL] [STATIC | KEYSET | DYNAMIC | FAST_FORWARD]
   [READ_ONLY | SCROLL_LOCKS | OPTIMISTIC] [TYPE_WARNING] FOR select_statement;

--2. 打开游标:
   OPEN cursor_name;


--3. 获取游标中的行数据:
   FETCH NEXT FROM cursor_name INTO variable1, variable2, ...;


--4. 关闭游标:
   CLOSE cursor_name;


--5. 释放游标的资源:
   DEALLOCATE cursor_name;

7.1.2示例应用

声明一个名为CustomerCursor的游标,并设置一些选项,如游标的定位、类型和可滚动性等:

DECLARE @CustomerId INT
DECLARE @CustomerName VARCHAR(100)

DECLARE CustomerCursor CURSOR 
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR 
SELECT CustomerId, CustomerName FROM Customers

OPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO @CustomerId, @CustomerName

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 在这里处理游标数据
    ...
    
    FETCH NEXT FROM CustomerCursor INTO @CustomerId, @CustomerName
END

CLOSE CustomerCursor
DEALLOCATE CustomerCursor

以Customers表为准,使用游标来处理 Customers 表中数据的示例:

 

SQL语句如下: 

--显示游标
-- 声明变量
DECLARE @CustomerId INT;
DECLARE @CustomerName VARCHAR(100);

-- 执行查询并循环处理每一行数据
DECLARE cur CURSOR FOR 
SELECT CustomerId, CustomerName 
FROM Customers;

OPEN cur;

FETCH NEXT FROM cur INTO @CustomerId, @CustomerName;
WHILE @@FETCH_STATUS = 0
BEGIN
    -- 在这里处理游标数据

    -- 例如,打印客户ID和名称
    PRINT 'Customer ID: ' + CAST(@CustomerId AS VARCHAR(10));
    PRINT 'Customer Name: ' + @CustomerName;

    -- 获取下一行数据
    FETCH NEXT FROM cur INTO @CustomerId, @CustomerName;
END

CLOSE cur;
DEALLOCATE cur;

 输出结果如下:

注意:

在使用显式游标时,需要显式地打开、关闭和释放游标。这与隐式游标不同,隐式游标在执行查询时会自动创建和释放。

7.2隐式游标

    隐式游标与具体的查询语句相关,并且不需要显式声明或控制。例如,在使用 SELECT 查询时,系统会自动创建一个隐式游标,并将结果集存储在该游标中。

7.2.1语法格式:

SELECT column1, column2, ...
FROM table_name
WHERE condition;

使用SELECT语句来查询需要遍历的数据,并指定需要选择的列(column1, column2, …)。我们还可以使用WHERE子句来指定条件,以筛选需要的行。

隐式声明游标的关键在于使用SELECT语句来选择数据,并将结果集作为游标的数据源。执行SELECT语句时,SQL Server会自动创建一个默认的游标,将结果集存储在游标中以供后续处理。

注意:

隐式声明游标是基于SELECT语句的结果集的,因此它的功能相对简单。我们可以在SELECT语句中使用复杂的查询和条件来获取所需的数据,并随后使用遍历循环(如WHILE循环)来逐行处理这些数据。 

在使用隐式游标时,我们无需显式打开、关闭或释放游标。系统会自动管理游标的生命周期,并在需要时获取结果集中的行数据。

7.2.2示例应用

【例1】检索Customers1表中城市为"New York"的客户的CustomerId和CustomerName列

-- 查询需要遍历的数据
SELECT CustomerId, CustomerName
FROM Customers1
WHERE City = 'New York';

执行这个SELECT语句后,SQL Server会自动创建一个隐式游标,并将查询结果存储在游标中。

【例2】使用遍历循环(例如WHILE循环)来逐行处理游标中的数据,以实现对结果集的逐行操作

-- 使用 WHILE 循环遍历隐式游标中的行

DECLARE @variable1 data_type, @variable2 data_type, ...;
 
-- 执行查询并获取结果集中的行数据
SELECT @variable1 = column1, @variable2 = column2, ...
FROM table_name
WHERE condition;

-- 循环处理每一行数据
WHILE @@FETCH_STATUS = 0
BEGIN
   -- 在这里处理行数据
   ...

   -- 获取下一行数据
   SELECT @variable1 = column1, @variable2 = column2, ...
   FROM table_name
   WHERE condition;
END

 依旧以Customers表为准,使用隐式游标while循环来处理 Customers 表中数据,SQL语句如下:

-- 声明变量
DECLARE @CustomerId INT;
DECLARE @CustomerName VARCHAR(100);

-- 执行查询并循环处理每一行数据
SELECT @CustomerId = MIN(CustomerId) FROM Customers;

WHILE @CustomerId IS NOT NULL
BEGIN
    -- 获取当前行的其他列数据
    SELECT @CustomerName = CustomerName 
    FROM Customers 
    WHERE CustomerId = @CustomerId;

    -- 在这里处理当前行数据

    -- 例如,打印客户ID和名称
    PRINT 'Customer ID: ' + CAST(@CustomerId AS VARCHAR(10));
    PRINT 'Customer Name: ' + @CustomerName;
    PRINT 'Customer Name (uppercase): ' + UPPER(@CustomerName);

    -- 获取下一行的CustomerID
    SELECT @CustomerId = MIN(CustomerId) 
    FROM Customers 
    WHERE CustomerId > @CustomerId;
END

在示例中,我是首先使用SELECT语句获取Customers表中最小的CustomerId,并将其赋值给变量@CustomerId。然后,进入一个WHILE循环,只要@CustomerId不为NULL,就会一直执行循环体内的操作。

在循环体内,我使用SELECT语句根据当前的@CustomerId获取对应的CustomerName,并将其赋值给变量@CustomerName。

接下来,我可以在循环体内处理当前行数据,例如打印客户ID和名称。在示例中,我是使用PRINT语句来打印变量的值,并且打印每一行的客户ID和大写的客户名称。

最后,我再使用SELECT语句获取下一个大于当前@CustomerId的最小CustomerId,并将其赋值给@CustomerId,以准备处理下一行数据。

通过循环遍历Customers表中的每一行数据,并在循环体内处理每一行的数据,例如打印客户ID和名称。

执行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1253411.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nodejs+vue+python+PHP+微信小程序-书吧租阅管理系统的设计与实现-安卓-计算机毕业设计

在当今高度发达的信息中&#xff0c;信息管理改革已成为一种更加广泛和全面的趋势。为确保中国经济的持续发展&#xff0c;信息时代日益更新&#xff0c;书吧租阅管理系统仍在蓬勃发展。同时&#xff0c;随着信息社会的快速发展&#xff0c;各种管理系统面临着越来越多的数据需…

leetcode刷题日志-15.三数之和

这道题还是有点难度&#xff0c;我能想到的就是三重循环&#xff0c;但是题目限制不能重复&#xff0c;所以这道题三重循环完还要去重&#xff0c;太过于麻烦。看了题解以后&#xff0c;大佬们还是厉害&#xff0c;大概思路是这样子的&#xff1a;先对数组进行排序&#xff0c;…

pandas根据列正逆序排序

题目&#xff1a;根据 buy_quantity 列进行排名&#xff0c;相同值分配相同的最低排名。 import pandas as pd# 创建一个示例 DataFrame data {item_id: [1, 2, 3, 4, 5, 6, 7], buy_quantity: [1, 2, 2, 3, 3, 4, 5]} df pd.DataFrame(data)# 使用 rank() 函数为 buy_quant…

电商数据|淘宝商品数据接口接入|参数|获取商品订单物流|电商数据分析

授权认证 授权不是开放平台对服务商应用的授权 &#xff0c;而是需要开放平台的客户&#xff08;用户&#xff09;对服务商应用的授予&#xff0c;比如ERP应用&#xff0c;也就是淘宝的店铺商家对应用进行授权&#xff0c;使其能够拉取到店铺的订单来完成订单履约。 淘宝授权页…

C++ day39 动态规划 不同路径 不同路径Ⅱ

题目1&#xff1a;62 不同路径 题目链接 &#xff1a;不同路径 对题目的理解 机器人位于m*n的网格中的左上角start,求解走到网格右下角finish的移动路径 动规五部曲 1&#xff09;dp数组的含义以及下标i的含义 dp[i][j]&#xff1a;从start&#xff08;0&#xff0c;0&…

继承性和多态性实验

继承性和多态性实验 一、实验题目二、实验目的三、实验内容与实现1&#xff1a;【实验内容】2:【实验实现】雇员类&#xff08;Employee&#xff09;的实现&#xff0c;如下图所示&#xff1a;2&#xff1a;经理类&#xff08;Manager&#xff09;的实现&#xff0c;如下图所示…

Feast:概念

实体 实体是语义相关特征的集合。用户定义实体以映射其用例的领域。 例如&#xff0c;打车车服务可以将客户和司机作为实体&#xff0c;这些实体将相关特征分组&#xff0c;对应于这些客户和司机。 driver Entity(namedriver, join_keys[driver_id]) # 司机实体 customer E…

⑨【Stream】Redis流是什么?怎么用?: Stream [使用手册]

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ ⑨Redis Stream基本操作命令汇总 一、Redis流 …

系列十六、Spring IOC容器的扩展点

一、概述 Spring IOC容器的扩展点是指在IOC加载的过程中&#xff0c;如何对即将要创建的bean进行扩展。 二、扩展点 2.1、BeanDefinitionRegistryPostProcessor 2.1.1、概述 BeanDefinitionRegistryPostProcessor是bean定义的后置处理器&#xff0c;在BeanDefinition加载后&a…

HarmonyOS应用开发者高级认证【题库答案】

HarmonyOS应用开发者基础认证【题库答案】 一、判断题 云函数打包完成后&#xff0c;需要到AppGallery Connect创建对应函数的触发器才可以在端侧中调用&#xff08;错&#xff09;在column和Row容器组件中&#xff0c;aligntems用于设置子组件在主轴方向上的对齐格式&#xf…

BUUCTF [HBNIS2018]低个头 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 得到的 flag 请包上 flag{} 提交。来源&#xff1a; https://github.com/hebtuerror404/CTF_competition_warehouse_2018 密文&#xff1a; 下载附件&#xff0c;得到一个.txt文件。 解题思路&#xff1a; 1、低头…

数字图像处理-Matlab实验

实验一 图像增强 实验内容: 对于给定的低对比度测试图像,利用灰度图像直方图均衡化算法进行图像视觉效果增强。 对于给定的低照度彩色测试图像,结合颜色空间转换和灰度图像直方图均衡化算法进行图像视觉效果增强。 实验数据: Test1_1.jpg: Test1_2.jpg: 实验步骤: %% …

基于ncurse实现的俄罗斯方块

1. 需求分析 方块的类型方块的变形方块的消除方块的存储方块的移动接受用户的输入 2. 概要设计 2.1 方块类型与变形 一共有七种&#xff0c;变换的方式如下。变换后的任意形状方块实际上可以存在一个4x4的矩阵中。 我们再压一下位&#xff0c;就可以存在16位中。 2.2 方块…

python之静态服务器程序开发

文章目录 Python静态Web服务器开发Web静态服务器初识搭建Python自带的静态Web服务器静态Web服务器返回固定页面数据静态Web服务器返回指定页面数据静态Web服务器多任务版静态Web服务器面向对象开发静态Web服务器命令行启动动态绑定端口号 Python静态Web服务器开发 Web静态服务…

求集合的笛卡尔乘积

求集合的笛卡尔乘积 一&#xff1a;【实验目的】二&#xff1a;【实验内容】三&#xff1a;【实验原理】四&#xff1a;代码实现&#xff1a; 一&#xff1a;【实验目的】 通过编实现给定集合A和B的笛卡尔积CAA,DAB,EBA,FAAB,GA(A*B&#xff09;. 二&#xff1a;【实验内容】…

Linux系统常用指令大全(图文详解)

目录 前言 一、UNIX的登录与退出 1、登录 &#xff08;1&#xff09;执行格式&#xff1a; &#xff08;2&#xff09;步骤 2、退出 二、UNIX命令格式 三、常用命令 1、目录操作 &#xff08;1&#xff09;显示目录文件 ls &#xff08;2&#xff09;建新目录 …

PgSQL技术内幕-Analyze做的那些事-pg_stat_all_tables

PgSQL技术内幕-Analyze做的那些事-pg_stat_all_tables pg_stat_all_tables视图中记录有analyze信息&#xff0c;比如何时做的analyze、表元组个数&#xff08;活元组、死元组&#xff09;等。重启后发现该视图中表的统计信息重置不见了&#xff0c;发生了什么&#xff1f; 1、p…

纵观手机市场,手机即鏖战全面屏

9月13日&#xff0c;在相继发布Apple TV、Apple Watch 和iPhone 8/8 Plus之后&#xff0c;当大家都以为苹果新品发布会临近结束之时&#xff0c;苹果前CEO史蒂夫乔布斯的这句经典名言再现屏幕&#xff0c;iPhone X终于揭开了神秘面纱。 “One more thing”。 9月13日&#xff…

Java每日一题:26. 删除有序数组中的重复项

删除有序数组中的重复项 分析&#xff1a; 数组是有序的&#xff0c;因此重复的元素会相邻 每次取出两个数进行比较&#xff0c;因此&#xff0c;需要有两个变量去存储每次取出的值 采用双指针方法&#xff1a; 指针p和q&#xff0c; pnum1&#xff0c;qnum2 p和q进行比较&…

【服务器能干什么】搭建一个短网址平台,可以查看数据详情!

昨天在 YouTube 上看到又一个搭建自己短网址的视频教程&#xff0c;用的是开源的 polr&#xff0c;但是按照步骤一步步搭建下来&#xff0c;最后一步都会出现 顺哥轻创 PLAINTEXT Whoops, looks like something went wrong百度、谷歌查了一圈也没找到有效的解决方法。&#x…