一、游标的基础知识

游标是。我们可以把游标当作一个指针,它可以指定结果中的任何位置,然后允许用户对指定位置的数据进行处理。

      游标包含两个部分:一个是游标结果集、一个是游标位置。

      游标结果集:定义该游标得SELECT语句返回的行的集合。游标位置:指向这个结果集某一行的当前指针。

 使用游标的顺序: 声名游标、打开游标、读取数据、关闭游标、删除游标。 

1、声明游标DECLARE <游标名> [INSENSITIVE] [SCROLL] CURSORFOR<SELECT语句> 

简单声明方式:DECLARE <游标名>CURSOR FOR<SELECT语句>

  • INSENSITIVE :表明MS SQL SERVER 会将游标定义所选取出来的数据记录存放在一临时表内(建立在tempdb 数据库下)。对该游标的读取操作皆由临时表来应答。因此,对基本表的修改并不影响游标提取的数据,即游标不会随着基本表内容的改变而改变,同时也无法通过游标来更新基本表。如果不使用该保留字,那么对基本表的更新、删除都会反映到游标中。 

另外应该指出,当遇到以下情况发生时,游标将自动设定INSENSITIVE 选项。 

a.在SELECT 语句中使用DISTINCT、 GROUP BY、 HAVING UNION 语句; 

b.使用OUTER JOIN; 

c.所选取的任意表没有索引; 

d.将实数值当作选取的列。 

  • SCROLL :表明所有的提取操作(如FIRST、 LAST、 PRIOR、 NEXT、 RELATIVE、 ABSOLUTE)都可用。如果不使用该保留字,那么只能进行NEXT 提取操作。由此可见,SCROLL 极大地增加了提取数据的灵活性,可以随意读取结果集中的任一行数据记录,而不必关闭再重开游标。
  1. NEXT :游标指针指向下一行。由于打开游标后,行指针是指向该游标第1行之前,所以第一次执行FETCH NEXT操作将取得游标集中的第1行数据。NEXT为默认的游标提取选项;
  2. PRIOR :上一行;
  3. FIRST:第一行;
  4. LAST :最后一行;
  5. ABSOLUTE(n):直接跳到第n行;
  6. RELATIVE(n):相对于目前跳几行,n>0则向下移动n行;n<0则向上移动n行;

2、 打开游标 

OPEN 游标名

3、读取数据 

FETCH [ NEXT | PRIOR | FIRST | LAST] FROM { 游标名  | @游标变量名 } [ INTO @变量名 [,…] ]  

  • INTO @变量名[,…]  将游标指向的行数据取出赋给局部变量。列表中的各个变量从左到右要与与游标结果集中的相应列相关联。各变量的数据类型必须与相应的结果列的数据类型匹配或是结果列数据类型所支持的隐性转换。变量的数目必须与游标选择列表中的列的数目一致。 

4、关闭游标 

CLOSE 游标名

5、释放游标 

DEALLOCATE 游标名 

6、@@fetch_status全局变量:返回针对连接当前打开的任何游标发出的最后一条游标 FETCH 语句的状态;

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

@@fetch_status值的改变是通过fetch next from实现的

二、示例:

步骤:

  1. 声明变量,用于保存游标取出的数据;
  2. 声明游标;
  3. 打开游标;
  4. 从游标取数赋给之前声明的变量;
  5. 对变量的数据进行操作;
  6. 关闭游标;
  7. 释放游标;

例:

create proc NK_FXSLTJ
as
declare @LCMC varchar(60), @num numeric     --声明游标需要使用的变量
declare My_Cursor2 cursor      --声明游标
for (select NKFXJZ_FXZ,NKLCK_MC from NKFXJZ join NKFXJZMX on NKFXJZMX_JZNM=NKFXJZ_NM join 
NKJZZZMX on NKJZZZMX_FXJZMX =NKFXJZMX_NM JOIN NKLCK ON NKLCK_NM =NKJZZZMX_LCNM )
open My_Cursor2;	  --打开游标
fetch next from My_Cursor2 into @num,@LCMC;   	--移动游标
while @@FETCH_STATUS =0	  	--判断 FETCH 语句是否成功
  begin 
	    if @num>=3.5 and @num<=5 
		      update SLTJ set GFX=GFX+1 where LCKMC=@LCMC 
	    else if @num>2 and @num<3.5 
		      update SLTJ set ZFX=ZFX+1 where LCKMC=@LCMC 
	    else if @num>=0 and @num<=2 
		      update SLTJ set DFX=DFX+1 where LCKMC=@LCMC 
	    fetch next from My_Cursor2 into @num,@LCMC; 	--移动游标
  end
close My_Cursor2;	--关闭游标
deallocate My_Cursor2;	--释放游标select LCKMC ,GFX ,ZFX ,DFX from SLTJ