sqlserver之游标

什么是游标?
对数据查询结果集的一种访问机制,逐条访问,也可以指定特定的行。

作用
定位到结果集中的某一行,对当前位置的数据进行读写。
缺点
数据读取出来放到内存中,但是内存空间有限,所以不能读取数量太大的,适用于数据量小的情况

分类

(1)静态游标

 静态游标在打开时会将数据集存储在tempdb(l临时数据库)中,因此显示的数据与游标打开时的数据集保持一致,在游标打开以后对数据库的更新不会显示在游标中。

(2)动态游标,
在打开后会反映对数据库的更改。所有UPDATE、INSERT 和 DELETE 操作都会显示在游标的结果集中,结果集中的行数据值、顺序和成员在每次提取时都会改变。

(3)只进游标
不支持前后滚动,只能从前读到尾,对数据库所做的更改在提取的时候在结果集中是可见的,但是如果在游标中已经对这条数据做了提取,那么在数据库中对条数据做的更改在结果集是看不到变化的,还是更改之前的样子。

(4)总结

静态游标在滚动的时候检测不到外部对数据库做的处理,所以消耗的资源相对较少。
动态游标在滚动的时候就能检测到外部数据库表数据的实时变化,消耗资源相对较多。
只进游标不支持滚动,只能向后读取
 游标的生命周期
声明-打开-读取数据-关闭-释放游标

创建游标

(1)只进游标

--1.定义只进游标  
declare user_cursor cursor local --global则表示是全局游标
for
--for后面写查询数据的t-sql
select id,name,account from [dbo].[User]
--2.打开游标
open user_cursor
--定义参数接收查询的结果 @varCursor用来存放单行数据的
declare @varCursor cursor,@cid int,@cname nvarchar(50),@caccount nvarchar(50)
set @varCursor=user_cursor
--3.提取数据  next:向下 prior:向上  first:第一个数据  last:最后一个数据  
--relative n :从当前位置开始第n条 相对位置
--absolute n :从一条数据算起的第n条 绝对位置
fetch next from @varCursor into @cid, @cname,@caccount --游标前进 into赋值
while @@FETCH_STATUS=0--判断是否提取成功
begin
 --打印数据
 print cast(@cid as varchar) +','+@cname+','+@caccount
 if(@cid=1)
 update [dbo].[User] set Name='李四2'  where  id=2
 if(@cid=2)
 update [dbo].[User] set Name='张三1'  where  id=1 
 --打印成功之后接着执行下面语句,表示接着提取下一条数据,
 fetch next from @varCursor into @cid, @cname,@caccount 
end
--4.关闭游标
close user_cursor
--5.释放游标
deallocate user_cursor

结果:

1,张三,在开会111

(1 行受影响)
2,李四2,在吃饭

(1 行受影响)
3,王二,在睡觉
4,张三,在睡觉1
5,3,3

看上面cid等于1 的时候更改id等于2的数据,cid等于2的时候更改id等于1的数据,最后的结果集中显示只有id等于2的在结果集中有变化,所以对数据库所做的更改在提取的时候在结果集中是可见的,但是如果在游标中已经对这条数据做了提取,那么在数据库中对条数据做的更改在结果集是看不到变化的,还是更改之前的样子。就是说提取之前做更改,结果集中显示的就是最新的,提取之后做更改,就算是在这个游标中,结果集中看到的还是更改之前的。

(2)静态游标

--1.定义静态游标   添加了static关键字
declare user_cursor_static cursor static local --global则表示是全局游标 
for
--for后面写查询数据的t-sql
select id,name,account from [dbo].[User]
--2.打开游标
open user_cursor_static
--定义参数接收查询的结果 @varCursor用来存放单行数据的
declare @varCursor cursor,@cid int,@cname nvarchar(50),@caccount nvarchar(50)
set @varCursor=user_cursor_static
--3.提取数据  next:向下 prior:向上  first:第一个数据  last:最后一个数据  
--relative n :从当前位置开始第n条 相对位置
--absolute n :从一条数据算起的第n条 绝对位置
fetch next from @varCursor into @cid, @cname,@caccount --游标前进 into赋值
while @@FETCH_STATUS=0--判断是否提取成功
begin
 --打印数据
 print cast(@cid as varchar) +','+@cname+','+@caccount
 if(@cid=1)
 update [dbo].[User] set Name='李四211'  where  id=2
 if(@cid=2)
 update [dbo].[User] set Name='张三111'  where  id=1 
 --打印成功之后接着执行下面语句,表示接着提取下一条数据,
 fetch next from @varCursor into @cid, @cname,@caccount 
end
--4.关闭游标
close user_cursor_static
--5.释放游标
deallocate user_cursor_static

结果:

1,张三11,在开会111

(1 行受影响)
2,李四21,在吃饭

(1 行受影响)
3,王二,在睡觉
4,张三,在睡觉1
5,3,3

使用静态游标,在游标打开以后对数据库的更新不会显示在游标的结果集中。除非再次执行一次游标才会看到

(3)动态游标

--1.定义动态游标  添加dynamic关键字
declare user_cursor_dynamic cursor dynamic local --global则表示是全局游标
for
--for后面写查询数据的t-sql
select id,name,account from [dbo].[User]
--2.打开游标
open user_cursor_dynamic
--定义参数接收查询的结果 @varCursor用来存放单行数据的
declare @varCursor cursor,@cid int,@cname nvarchar(50),@caccount nvarchar(50)
set @varCursor=user_cursor_dynamic
--3.提取数据  next:向下 prior:向上  first:第一个数据  last:最后一个数据  
--relative n :从当前位置开始第n条 相对位置
--absolute n :从一条数据算起的第n条 绝对位置
fetch next from @varCursor into @cid, @cname,@caccount --游标前进 into赋值
while @@FETCH_STATUS=0--判断是否提取成功
begin
 --打印数据
 print cast(@cid as varchar) +','+@cname+','+@caccount
 if(@cid=1)
 update [dbo].[User] set Name='李四211'  where  id=2
 if(@cid=2)
 begin
 --更改当前数据
 --update [dbo].[User] set Name='张三111'  where  current of user_cursor_dynamic
 update [dbo].[User] set Name='张三111'  where  id=1 
 fetch first from @varCursor into @cid, @cname,@caccount --注意,这里会存在死循环
 end
 --打印成功之后接着执行下面语句,表示接着提取下一条数据,
 fetch next from @varCursor into @cid, @cname,@caccount 
end
--4.关闭游标
close user_cursor_dynamic
--5.释放游标
deallocate user_cursor_dynamic

如果数据做了更改,而且这条数据已经提取出来了 ,那么不用关闭这个游标,可以在这个游标中再次查询就会查出更改后的数据。

原文地址:https://www.cnblogs.com/anjingdian/p/15388601.html