游标
游标其实可以理解成一个定义在特定数据集上的指针,我们可以控制这个指针遍历数据集,或者仅仅是指向特定的行,所以游标是定义在以Select开始的数据集上的
1、定义游标
DECLARE cursor_name CURSOR [ LOCAL | GLOBAL ] --LOCAL意味着游标的生存周期只在批处理或函数或存储过程中可见,而GLOBAL意味着游标对于特定连接作为上下文,全局内有效
[ FORWARD_ONLY | SCROLL ] --FORWARD_ONLY意味着游标只能从数据集开始向数据集结束的方向读取,FETCH NEXT是唯一的选项,而SCROLL支持游标在定义的数据集中向任何方向,或任何位置移动
[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ] --这四个关键字是游标所在数据集所反应的表内数据和游标读取出的数据的关系
--STATIC意味着,当游标被建立时,将会创建FOR后面的SELECT语句所包含数据集的副本存入tempdb数据库中,任何对于底层表内数据的更改不会影响到游标的内容.
--DYNAMIC是和STATIC完全相反的选项,当底层数据库更改时,游标的内容也随之得到反映,在下一次fetch中,数据内容会随之改变
--KEYSET可以理解为介于STATIC和DYNAMIC的折中方案。将游标所在结果集的唯一能确定每一行的主键存入tempdb,当结果集中任何行改变或者删除时,@@FETCH_STATUS会为-2,KEYSET无法探测新加入的数据
--FAST_FORWARD可以理解成FORWARD_ONLY的优化版本.FORWARD_ONLY执行的是静态计划,而FAST_FORWARD是根据情况进行选择采用动态计划还是静态计划,大多数情况下FAST_FORWARD要比FORWARD_ONLY性能略好.
[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]
--READ_ONLY意味着声明的游标只能读取数据,游标不能做任何更新操作
-- SCROLL_LOCKS是另一种极端,将读入游标的所有数据进行锁定,防止其他程序进行更改,以确保更新的绝对成功
-- OPTIMISTIC是相对比较好的一个选择,OPTIMISTIC不锁定任何数据,当需要在游标中更新数据时,如果底层表数据更新,则游标内数据更新不成功,如果,底层表数据未更新,则游标内表数据可以更新
[ TYPE_WARNING ]
FOR select_statement
[ FOR UPDATE [ OF column_name [ ,...n ] ] ]
[;]
*全局变量定义后直接赋值
2、打开游标
3、使用游标
4、关闭游标
5、释放游标
插入表
create table books ( book_id int identity(1,1) primary key, book_name varchar(20), book_price float, book_auth varchar(10) ); --插入测试数据 insert into books (book_name,book_price,book_auth) values ('论语',25.6,'孔子'), ('天龙八部',25.6,'金庸'), ('雪山飞狐',32.7,'金庸'), ('平凡的世界',35.8,'路遥'), ('史记',54.8,'司马迁'); SELECT * FROM books
使用游标案例
declare boob cursor scroll for select book_name,book_price,book_auth from books open boob declare @book_name varchar(20),@book_price float,@book_auth varchar(10) fetch next from boob into @book_name,@book_price,@book_auth print '书籍名称:'+@book_name+',价格:'+convert(varchar(20),@book_price)+',作者:'+@book_auth while (@@FETCH_STATUS=0) begin fetch next from boob into @book_name,@book_price,@book_auth print '书籍名称:'+@book_name+',价格:'+convert(varchar(20),@book_price)+',作者:'+@book_auth end close boob deallocate boob
if (object_id('book_cursor', 'P') is not null)--带游标的存储过程 drop proc book_cursor go create proc book_cursor @bookCursor cursor varying output as set @bookCursor=cursor forward_only static for select book_id,book_name,book_auth from books open @bookCursor; go --调用book_cursor存储过程 declare @cur cursor, @bookID int, @bookName varchar(20), @bookAuth varchar(20); exec book_cursor @bookCursor=@cur output; fetch next from @cur into @bookID,@bookName,@bookAuth; while(@@FETCH_STATUS=0) begin fetch next from @cur into @bookID,@bookName,@bookAuth; print 'bookID:'+convert(varchar,@bookID)+' , bookName: '+ @bookName +' ,bookAuth: '+@bookAuth; end close @cur --关闭游标 DEALLOCATE @cur; --释放游标