SqlServer(游标)

游标是什么?

对数据查询结果集的一种访问机制,用户对结果集进行逐条访问,单条数据,操作对象 :结果集
可以理解为:定义在特定结果集上的指针,控制这个指针,遍历 数据集或指定特定的行。
游标的作用:定位到结果集中的某一行,对当前位置的数据进行读写。
缺点:数据读取出来放到内存,--内存空间有限,如果数据量太大,内存空间不足.
适用于:数据量小的情况。
注:一般来说,能使用其他方式处理数据时,最好不要使用游标,除非是其他方式都无法处理时,才使用,不适合数据量大的情况。

游标分类

静态游标:支持滚动,,结果集都不会变,结果集与操作之后的数据一致;---除非关闭游标,再重新打开
动态游标:支持滚动,对数据库如何操作,结果集获取所有的改变,提取时,行数据、顺序、成员都会发生变化,对数据库的操作都通过游标可见。游标外部所做的更新直到提交时才可见。
只进游标:不支持滚动,从头读到尾,读取前对数据库所做更改在提取时是可见的(读到更改后的)。因为只进不退。提取后所做的更改是不可见的。(也更新到数据库了)
键集驱动游标:打开游标时,表中各个成员身份、顺序是固定的。结果集被一组唯一标识符标识,被标识列更改时,滚动游标时,是可见的;没被标识的列,则不可见。
动态游标和只进游标都会在更新数据库后更新结果集

静态游标

静态游标支持前后滚动,但在执行过程中,是不能获取数据的改变

--声明游标
declare book_cursor_static cursor static local
for 
select BookId,BookName,BookCount,Price from BookInfos where IsDeleted=0
----打开游标
open book_cursor_static
----声明游标变量   局部变量
declare @varCursor cursor,@bookId int,@bookName nvarchar(50),@bookCount int,@price decimal(18,2)
set @varCursor=book_cursor_static  --游标变量赋值
----读取  next 下一条 prior 上一条  first 第一条  last 最后一条  absolute n 绝对位置  relative n 从当前位置开始的第n条
fetch next from @varCursor into @bookId,@bookName,@bookCount,@price
while @@fetch_status=0  --判断读取是否成功
begin
   print cast(@bookId as varchar)+','+@bookName+','+convert(varchar,@bookCount)+','+cast(@price as varchar);
   if @bookId=1128 and @bookCount=150
    begin
      update BookInfos set BookCount=120 where BookId=@bookId
      fetch first from @varCursor into @bookId,@bookName,@bookCount,@price
   end
   else
     fetch next from @varCursor into @bookId,@bookName,@bookCount,@price
end
close book_cursor_static  --关闭
deallocate book_cursor_static  --释放游标
--数据库更改后怎么读,结果集都不变

动态游标

declare book_cursor_dynamic cursor dynamic local
for 
select BookId,BookName,BookCount,Price from BookInfos where IsDeleted=0
--打开游标
open book_cursor_dynamic
--声明游标变量   局部变量
declare @varCursor cursor,@bookId int,@bookName nvarchar(50),@bookCount int,@price decimal(18,2)
set @varCursor=book_cursor_dynamic  --游标变量赋值
--读取  next 下一条 prior 上一条  first 第一条  last 最后一条  absolute n 绝对位置  relative n 从当前位置开始的第n条
fetch next from @varCursor into @bookId,@bookName,@bookCount,@price
while @@fetch_status=0  --判断读取是否成功
begin
   print cast(@bookId as varchar)+','+@bookName+','+convert(varchar,@bookCount)+','+cast(@price as varchar);
   if @bookId=1130 and @bookCount=70
    begin
      update BookInfos set BookCount=60 where current of book_cursor_dynamic
      fetch first from @varCursor into @bookId,@bookName,@bookCount,@price
   end
   else
     fetch next from @varCursor into @bookId,@bookName,@bookCount,@price
end
close book_cursor_dynamic  --关闭
deallocate book_cursor_dynamic  --释放游标
--数据库改后,重新读会读到更新后的结果集

只进游标

--只进游标   从头到尾的读  只能用next    一般主要用来读数据,但可以修改数据
declare book_cursor cursor local
for 
select BookId,BookName,BookCount,Price from BookInfos where IsDeleted=0
--打开游标
open book_cursor
--声明游标变量   局部变量
declare Stu_cursor cursor local
for 
select StuId,StuName,Sex,Phone from StudentInfos where IsDeleted=0
--打开游标
open Stu_cursor
--声明游标变量   局部变量
declare @varCursor cursor,@StuId int,@StuName nvarchar(50),@Sex nvarchar(2),@Phone nvarchar(50)
set @varCursor=Stu_cursor  --游标变量赋值
--读取  next 下一条 prior 上一条  first 第一条  last 最后一条  absolute n 绝对位置  relative n 从当前位置开始的第n条
fetch next from @varCursor into @StuId,@StuName,@Sex,@Phone
while @@fetch_status=0  --判断读取是否成功
begin
	print cast(@StuId as varchar)+','+@StuName+','+convert(varchar,@Sex)+','+cast(@Phone as varchar);
	if @StuId=1010
		update StudentInfos set Phone='33322' where StuId=1012 --当读到1012后会发现phone更新为33322了
	fetch next from @varCursor into @StuId,@StuName,@Sex,@Phone
end
close Stu_cursor  
deallocate Stu_cursor  
--数据库改后,重新读会读到更新后的结果集

存储过程使用游标

alter proc procDealBookInfos
as
begin
  declare book_cursor_dynamic cursor dynamic local
for 
select BookId,BookName,BookCount,Price from BookInfos where IsDeleted=0
--打开游标
open book_cursor_dynamic
--声明游标变量   局部变量
declare @varCursor cursor,@bookId int,@bookName nvarchar(50),@bookCount int,@price decimal(18,2)
set @varCursor=book_cursor_dynamic  --游标变量赋值
--读取  next 下一条 prior 上一条  first 第一条  last 最后一条  absolute n 绝对位置  relative n 从当前位置开始的第n条
fetch next from @varCursor into @bookId,@bookName,@bookCount,@price
while @@fetch_status=0  --判断读取是否成功
begin
   print cast(@bookId as varchar)+','+@bookName+','+convert(varchar,@bookCount)+','+cast(@price as varchar);
   if @bookId=1130 and @bookCount=60
   begin
      update BookInfos set BookCount=80 where current of book_cursor_dynamic
      fetch first from @varCursor into @bookId,@bookName,@bookCount,@price
   end
   else
     fetch next from @varCursor into @bookId,@bookName,@bookCount,@price
end
close book_cursor_dynamic  --关闭
deallocate book_cursor_dynamic  --释放游标
end

exec procDealBookInfos
posted @ 2025-08-01 17:35  TheSheep2023  阅读(26)  评论(0)    收藏  举报