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