SQL使用游标对Select结果集循环操作

首先先简述一下SQL中游标的作用,我们可以将游标理解成一个数组或是一个队列,其保存了Select的结果集的地址队列。
当我们需要对Select的结果集进行循环操作时,可以先定义一个游标,并将结果集指向到这个游标当中,使用游标像指针一样访问这个结果集,如下

①声明游标

1
2
3
DECLARE @id INT --声明一个变量id
DECLARE cur CURSOR read_only FOR --声明一个名为cur的游标
SELECT Userid FROM UserTable WHERE ...... --某Select语句

上述代码意为声明一个游标指向某Select语句的结果集,read_only的意思是这个指针只用于读取,如果更新则需要使用update,这样做的好处是可以明确游标的针对性从而提高执行效率。
DECLARE @id int 意为声明一个变量id,后续会用于从游标指向的结果集中获取数据

创建完游标之后,现在需要打开这个游标并进行操作,语法如下:

②打开游标并读取游标数据

1
2
3
4
5
6
7
8
OPEN cur
Fetch NEXT FROM cur INTO @id --将cur中的下一个数据赋值给变量id

WHILE(@@FETCH_STATUS = 0)
BEGIN
    --要执行的SQL语句
    fetch NEXT FROM cur INTO @id
END

Fetch 的语法如下
Fetch [Next | Prior | First | Last | Absolute n | Relative n ] From 游标名 INTO @变量1,@变量2…

Next:返回结果集中当前行的下一行记录
Prior:返回结果集中当前行的前一行记录,如果第一次读取则没有行返回,并且把游标置于第一行之前。
First:返回结果集中的第一行记录,并且将其作为当前行。
Last:返回结果集中的最后一行,并且将其作为当前行。
Absolute n:当 n > 0 时返回从游标头开始的第n行,并且将其作为当前行;n < 0 时返回从游标末尾开始的第n行,并且将其作为当前行;n = 0 时返回当前行。
Relative n:当 n > 0 时返回从当前行之后的第n行;n < 0 时则返回当前行之前的第n行;n = 0 时返回当前行。

开启游标后,游标指针位于-1行,因此需要使用FETCH NEXT移动到Select的结果集的第一行,
WHILE(@@FETCH_STATUS = 0)循环判断是否有数据,满足条件时将执行Begin和End之间的语句。
每次执行完之后注意使用 Fetch NEXT 移动到下一行。

③关闭并删除游标

1
2
CLOSE cur
DEALLOCATE cur

此语句用于释放游标并将其删除,减少对数据库资源的消耗。

以下是一个完整版demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DECLARE @id INT
DECLARE cur CURSOR read_only FOR
SELECT DISTINCT [userid] FROM [UserTable] WHERE [userid] <= 10000
OPEN cur
fetch NEXT FROM cur INTO @id

while(@@FETCH_STATUS = 0)
BEGIN
        UPDATE [ScoreTable] SET [Score] = [Score] + 1000 WHERE userid = @id
        fetch NEXT FROM cur INTO @id
END

CLOSE cur
DEALLOCATE cur

上述语句意为在UserTable表中查找id号小于10000的用户,同时对这些用户的ScoreTable表中的Score值加1000
当然这个过程可以使用SQL表连接进行操作,并且效率高于游标,这里只是做一个举例,很多时候,游标还是可以做一些表连接很难做到的灵活操作的。

关于游标的一些注意事项:
游标的灵活性是建立在加大对服务器性能消耗的基础上的,因此使用游标可能会导致页锁与表锁的情况增加,所以在一些频繁操作的语句中尽可能的不要使用游标,使用一些相对优化的SQL语句来取代游标的作用。
同时可以在声明游标时使用Read_Only来标注次游标的用途,如 DECLARE cur CURSOR read_only FOR …

关于游标的使用和探讨还有很多,本文仅仅只是简单介绍了其使用方法和特点,更多内容欢迎交流。
本文到此,谢谢关注。

BeiTown
2013.07.30

本文链接:SQL使用游标对Select结果集循环操作

转载声明:BeiTown原创,转载请注明来源:BeiTown's Coder 编码之源,谢谢


Tags: , , ,

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>