SQL sever2008中的游标
目录
一、游标概述
二、游标的实现
三、优缺点
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
表中选择 column1
和 column2
列,并且只能以向前遍历的方式访问结果集。
【例2】全局可滚动可更新游标
DECLARE cursor_name CURSOR GLOBAL SCROLL
FOR UPDATE OF column1, column2
FOR SELECT column1, column2 FROM table_name;
示例声明一个全局的可滚动游标,它从 table_name
表中选择 column1
和 column2
列,并允许对这两列进行更新操作。
【例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
表中选择 column1
和 column2
列,并且允许对 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
表中选择 column1
和 column2
列,并且允许对这两列进行更新操作 .
【例6】静态可滚动游标
DECLARE cursor_name CURSOR STATIC SCROLL
FOR SELECT column1, column2 FROM table_name;
示例声明一个静态可滚动游标,从 table_name
表中选择 column1
和 column2
列。
【例7】键集游标
DECLARE cursor_name CURSOR KEYSET
FOR SELECT column1, column2 FROM table_name;
示例声明一个键集游标,从 table_name
表中选择 column1
和 column2
列。键集游标在打开时获取结果集的键值,并根据这些键值定位结果集中的行。
【例8】动态只进游标
DECLARE cursor_name CURSOR DYNAMIC FORWARD_ONLY
FOR SELECT column1, column2 FROM table_name;
示例声明一个动态只进游标,从 table_name
表中选择 column1
和 column2
列。动态只进游标每次都会重新执行查询,而不是缓存结果集。
【例9】全局并发锁游标
DECLARE cursor_name CURSOR GLOBAL SCROLL SCROLL_LOCKS
FOR SELECT column1, column2 FROM table_name;
示例声明一个全局并发锁游标,从 table_name
表中选择 column1
和 column2
列。全局并发锁游标允许其他事务以共享或排他方式访问相同的数据行。
【例10】局部快速向前仅警告游标
DECLARE cursor_name CURSOR LOCAL FAST_FORWARD TYPE_WARNING
FOR SELECT column1, column2 FROM table_name;
示例声明一个局部快速向前仅警告游标,从 table_name
表中选择 column1
和 column2
列。该游标以快速向前的方式遍历结果集,但在某些情况下会生成警告消息。
注意:
一定要根据自己的数据库结构和需求来编写适合的 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
BEGINFETCH 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,无默认值,可取值如下表所示。
值 | 说明 |
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)
BEGINFETCH 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)
BEGINFETCH NEXT from @Report
ENDCLOSE @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 CustomersOPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO @CustomerId, @CustomerNameWHILE @@FETCH_STATUS = 0
BEGIN-- 在这里处理游标数据...FETCH NEXT FROM CustomerCursor INTO @CustomerId, @CustomerName
ENDCLOSE 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;
ENDCLOSE 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_nameWHERE 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);-- 获取下一行的CustomerIDSELECT @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和名称。
执行结果如下:
相关文章:

SQL sever2008中的游标
目录 一、游标概述 二、游标的实现 三、优缺点 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语…...
在linux中进行文件的打包(打压缩)和解压
1.".tar " 格式(打包不会压缩) ".tar" 格式的打包和解打包都使用 tar 命令,区别只是选项不同。 ".tar" 格式打包命令: tar [选项] [-f 压缩包名] 源文件或目录 选项: -cÿ…...

mysql8下载与安装教程
文章目录 1. MySQL下载2. 方式一:msi文件安装2.1 安装2.2 添加环境变量2.3 登录mysql 3. 方式二:zip文件安装3.1 安装3.2 配置文件3.3 加入环境变量3.4 初始化mysql3.5 登录mysql 1. MySQL下载 以下两个网址二选一 官网:https://downloads.…...

ubuntu22.04在线安装redis,可选择版本
安装脚本7.0.5版本 在线安装脚本,默认版本号是7.0.5,可以根据需要选择需要的版本进行下载编译安装 sudo apt-get install gcc -y sudo apt-get install pkg-config -y sudo apt-get install build-essential -y#安装redis rm -rf ./tmp.log systemctl …...
MYSQL加密和压缩函数详解和实战(含示例)
MySQL提供了多种加密和压缩方式,可以帮助保护数据库中的敏感数据。以下是一些常见的MySQL加密和压缩方法参考: 建议收藏以备后续用到查阅参考。 目录 一、AES_ENCRYPT AES加密 二、AES_DECRYPT AES解密 三、COMPRESS 压缩字符串 四、UNCOMPRESS 解压…...

redis Redis::geoAdd 无效,phpstudy 如何升级redis版本
redis 查看当前版本命令 INFO SERVERwindows 版redis 进入下载 geoadd 功能在3.2之后才有的,但是phpstudy提供的最新的版本也是在3.0,所以需要升级下 所以想出一个 挂狗头,卖羊肉的方法,下载windows 的程序,直接替…...

2024重庆大学计算机考研分析
24计算机考研|上岸指南 重庆大学 重庆大学计算机考研招生学院是计算机学院和大数据与软件学院。目前均已出拟录取名单。 重庆大学计算机学院是我国高校最早开展计算机研究的基地之一,1978年和1986年获西南地区首个硕士和博士点,1998年成立计算机学院&a…...

二、Lua数据类型
文章目录 一、数据类型nil二、数据类型boolean三、数据类型number四、数据类型String(一)用单引号或双引号:(二)可以包含换行的字符串(三)字符串与数字做数学运算时,优先将字符串转换…...

Grabcut算法在图片分割中的应用
GrabCut算法原理 Grabcut是基于图割(graph cut)实现的图像分割算法,它需要用户输入一个bounding box作为分割目标位置,实现对目标与背景的分离/分割,与KMeans与MeanShift等图像分割方法不同。 Grabcut分割速度快,效果好࿰…...

常用的Linux的指令
目录 常用指令 1、文件和目录操作: 2、文件查看和编辑 3、系统信息 4、进程管理 5、用户和权限 6、网络操作 7、压缩和解压 8、软件包管理 常用指令 1、文件和目录操作: ls:列出目录内容 cd: 切换目录 pwd:显…...

【STM32】GPIO输出
1 GPIO简介 (1)GPIO(General Purpose Input Output)通用输入输出口 (2)可配置为8种输入输出模式 (3)引脚电平:0V~3.3V,部分引脚可容忍5V(可以输…...

【Go语言从入门到实战】反射编程、Unsafe篇
反射编程 reflect.TypeOf vs reflect.ValueOf func TestTypeAndValue(t *testing.T) {var a int64 10t.Log(reflect.TypeOf(a), reflect.ValueOf(a))t.Log(reflect.ValueOf(a).Type()) }判断类型 - Kind() 当我们需要对反射回来的类型做判断时,Go 语言内置了一个…...
vue实现对话框指定某个对话内容的滚动到指定位置(滚动到可视区域的中间位置)
1、使用el-scrollbar实现定位滚动(elementui组件库) 如何滚动:参考链接 比如说指定某条对话内容滚动到可视区域的中间 html结构: <div class"chat-list" id"chat-list"><el-scrollbar ref"scro…...
【RTP】2:RtpPacket、RtpPacketToSend 创建、修改的简要分析
【RTP】1: RTPSenderAudio::SendAudio继续对如何做修改,比如修改扩展 做分析。查找扩展 一个已知的已经在packet中存在的扩展bool RtpPacket::IsExtensionReserved(ExtensionType type) const {uint8_t id = extensions_.GetId(type);...

汽车租聘管理与推荐系统Python+Django网页界面+协同过滤推荐算法
一、介绍 汽车租聘管理与推荐系统。本系统使用Python作为主要编程语言,前端采用HTML、CSS、BootStrap等技术搭建前端界面,后端采用Django框架处理用户的请求。创新点:使用协同过滤推荐算法实现对当前用户个性化推荐。 其主要功能如下&#x…...

qt pdf 模块简介
文章目录 1. 技术平台2. Qt pdf 模块3. cmake 使用模块4. 许可证5. 简单示例5.1 CMakeLists.txt5.2 main.cpp 6. 总结 1. 技术平台 项目说明OSwin10 x64Qt6.6compilermsvc2022构建工具cmake 2. Qt pdf 模块 Qt PDF模块包含用于呈现PDF文档的类和函数。 QPdfDocument 类加载P…...
Spring Boot WebSocket 客户端
介绍 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它可以提供实时的、双向的数据传输。Spring Boot 提供了对 WebSocket 的支持,我们可以使用 Spring Boot WebSocket 客户端来连接到 WebSocket 服务器,并进行实时通信。 本文将…...
第五题-kotori和素因子【第六届传智杯程序设计挑战赛解题分析详解复盘】(JavaPythonC++实现)
🚀 欢迎来到 ACM 算法题库专栏 🚀 在ACM算法题库专栏,热情推崇算法之美,精心整理了各类比赛题目的详细解法,包括但不限于ICPC、CCPC、蓝桥杯、LeetCode周赛、传智杯等等。无论您是刚刚踏入算法领域,还是经验丰富的竞赛选手,这里都是提升技能和知识的理想之地。 ✨ 经典…...

【服务器能干什么】二十分钟搭建一个属于自己的 RSS 服务
如果大家不想自己捣鼓,只是想尝尝鲜,可以在下面留言,我后台帮大家开几个账号玩一玩。 哔哩哔哩【高清版本可以点击去吐槽到 B 站观看】:【VPS服务器到底能干啥】信息爆炸的年代,如何甄别出优质的内容?你可能需要自建一个RSS服务!_哔哩哔哩_bilibili 前言 RSS 服务 市…...
热门免费api接口:含核验API,物流api,短信api,天气api。。。
热门免费api接口:含核验API,物流api,短信api,天气api。。。 银行卡二要素:检测输入的姓名、银行卡号是否一致。毫秒级响应、直联保障,支持全国所有银联卡。银行卡三要素:检测输入的姓名、身份证号码、银行卡号是否一致。毫秒级响…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?
Redis 的发布订阅(Pub/Sub)模式与专业的 MQ(Message Queue)如 Kafka、RabbitMQ 进行比较,核心的权衡点在于:简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...

计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...

AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...