Sqlserver 游标

发布时间 2023-11-12 20:52:25作者: zhihua

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 ] ] ]
 
 

2,声明一个动态游标

declare orderNum_02_cursor cursor scroll
for select OrderId from bigorder where orderNum='ZEORD003402'

3,打开游标

--打开游标语法
open [ Global ] cursor_name | cursor_variable_name

cursor_name:游标名,cursor_variable_name:游标变量名称,该变量引用了一个游标。

--打开游标
open orderNum_02_cursor

4,提取数据

复制代码
--提取游标语法
Fetch
[ [Next|prior|Frist|Last|Absoute n|Relative n ]
from ]
[Global] cursor_name
[into @variable_name[,....]]
复制代码

 

参数说明:

  • Frist:结果集的第一行
  • Prior:当前位置的上一行
  • Next:当前位置的下一行
  • Last:最后一行
  • Absoute n:从游标的第一行开始数,第n行。
  • Relative n:从当前位置数,第n行。
  • Into @variable_name[,...] : 将提取到的数据存放到变量variable_name中。

例子:

复制代码
--提取数据
fetch first from orderNum_02_cursor
fetch relative 3 from orderNum_02_cursor
fetch next from orderNum_02_cursor
fetch absolute 4 from orderNum_02_cursor
fetch next from orderNum_02_cursor
fetch last from orderNum_02_cursor 
fetch prior from orderNum_02_cursor
select * from bigorder where orderNum='ZEORD003402'
复制代码

例子:

--提取数据赋值给变量
declare @OrderId int
fetch absolute 3 from orderNum_02_cursor into @OrderId
select @OrderId as id
select * from bigorder where orderNum='ZEORD003402'


通过检测全局变量@@Fetch_Status的值,获得提取状态信息,该状态用于判断Fetch语句返回数据的有效性。当执行一条Fetch语句之后,@@Fetch_Status可能出现3种值:

  • 0,Fetch语句成功。
  • -1:Fetch语句失败或行不在结果集中。
  • -2:提取的行不存在。

这个状态值可以帮你判断提取数据的成功与否。

复制代码
declare @OrderId int
fetch absolute 3 from orderNum_02_cursor into @OrderId
while @@fetch_status=0  --提取成功,进行下一条数据的提取操作
 begin
   select @OrderId as id
   fetch  next from orderNum_02_cursor into @OrderId  --移动游标
 end
复制代码

5.利用游标更新删除数据

--游标修改当前数据语法
Update 基表名 Set 列名=值[,...] Where Current of 游标名
--游标删除当前数据语法
Delete 基表名  Where Current of 游标名

游标更新删除当前数据

复制代码
--1.声明游标
declare orderNum_03_cursor cursor scroll
for select OrderId ,userId from bigorder where orderNum='ZEORD003402'
--2.打开游标
open orderNum_03_cursor
--3.声明游标提取数据所要存放的变量
declare @OrderId int ,@userId varchar(15)
--4.定位游标到哪一行
fetch First from orderNum_03_cursor into @OrderId,@userId  --into的变量数量必须与游标查询结果集的列数相同
while @@fetch_status=0  --提取成功,进行下一条数据的提取操作 
 begin
   if @OrderId=122182
     begin
     Update bigorder Set UserId='123' Where Current of  orderNum_03_cursor  --修改当前行
     end
   if @OrderId=154074
      begin
      Delete bigorder Where Current of  orderNum_03_cursor  --删除当前行
      end
   fetch next from orderNum_03_cursor into @OrderId ,@userId  --移动游标
 end
复制代码

6,关闭游标

  游标打开后,服务器会专门为游标分配一定的内存空间存放游标操作的数据结果集,同时使用游标也会对某些数据进行封锁。所以游标一旦用过,应及时关闭,避免服务器资源浪费。

--关闭游标语法
close [ Global ] cursor_name | cursor_variable_name
--关闭游标
close orderNum_03_cursor

7,删除游标

  删除游标,释放资源

--释放游标语法
deallocate  [ Global ] cursor_name | cursor_variable_name
--释放游标
deallocate orderNum_03_cursor

 

使用实例:

复制代码
USE Test_DB;

DECLARE @jid CHAR(5)
DECLARE @pic NVARCHAR(64)
DECLARE My_Cursor CURSOR --定义游标
FOR (SELECT jid FROM journal WHERE isall in(1,2)) --查出需要的集合放到游标中
OPEN My_Cursor; --打开游标
FETCH NEXT FROM My_Cursor INTO @jid; --读取第一行数据
WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @pic=(SELECT TOP 1 smallpic FROM journalissue WHERE jid=@jid and (smallpic != '' and smallpic is not null) ORDER BY issueyear DESC,issueno DESC);
        PRINT (@jid +'    '+ @pic);
        IF(@jid != '' and @jid is not null and @pic != '' and @pic is not null)
        BEGIN
            UPDATE journal SET pic=@pic WHERE jid=@jid;
        END        
        FETCH NEXT FROM My_Cursor INTO @jid; --读取下一行数据
    END
CLOSE My_Cursor; --关闭游标
DEALLOCATE My_Cursor; --释放游标
GO
复制代码


 

示例:

复制代码
 1 USE [Community];
 2 
 3 DECLARE @UserInfoID bigint,@Name nvarchar(100),@UCAccountID bigint;
 4 
 5 
 6 DECLARE My_Cursor CURSOR --定义游标
 7 FOR (
 8     select distinct(UI.[UserInfoID]),UI.[Name],UIToUC.[UCAccountID] from [dbo].[CMAreaRelation] as AR 
 9         inner join [dbo].[UserInfo] as UI on UI.[UserInfoID]=AR.[Creator]
10         inner join [dbo].[UserInfoToUCAccount] as UIToUC on UIToUC.[UserInfoID]=UI.[UserInfoID]
11 ) --查出需要的集合放到游标中
12 OPEN My_Cursor; --打开游标
13 FETCH NEXT FROM My_Cursor INTO @UserInfoID,@Name,@UCAccountID; --读取第一行数据
14 WHILE @@FETCH_STATUS = 0
15     BEGIN
16         PRINT '@UserInfoID='+convert(varchar,isnull(@UserInfoID,0))+', @Name='+isnull(@Name,'')+', @UCAccountID='+convert(varchar,isnull(@UCAccountID,0)); --打印,方便查看(正式项目不需要该行)
17         --这里是根据每一行编写自定义的操作……
18 
19         FETCH NEXT FROM My_Cursor INTO @UserInfoID,@Name,@UCAccountID; --读取下一行数据
20     END
21 CLOSE My_Cursor; --关闭游标
22 DEALLOCATE My_Cursor; --释放游标
23 GO