请帮我看看下面的游标有什么问题:
说明:tab表中有字段ID,adress.现在要重新编排ID,adress列相同的记录共用同一个ID.第一条记录的ID已经确定为1,往后依次递增.declare cur_tab cursor scroll for    
select ID,address from tab
declare @xuhao1 varchar(15),@xuhao2 varchar(15),@addr1 varchar(15),@addr2 varchar(15)
open cur_tab
fetch next from cur_tab into @xuhao1,@addr1
while @@fetch_status=0
begin  
  fetch next from cur_tab into @xuhao2,@addr2
  if @addr1=@addr2
     update tab set ID=@xuhao1 where current of cur_tab
  else 
    update tab set ID=@xuhao1+1 where current of cur_tab
  set @xuhao1=@xuhao2
  set @addr1=@addr2
end
close cur_tab                        
deallocate cur_tab   
执行结果有这样的提示:执行结果报错:
服务器: 消息 16930,级别 16,状态 1,行 10
所请求的行不在提取缓冲区内。
语句已终止。查看结果,发现只增加了一个新的ID.这样看来是没有正常循环,但是又找不到哪里有毛病,哪位帮我看看,谢谢!

解决方案 »

  1.   

    READ ONLY禁止通过该游标进行更新。在 UPDATE 或 DELETE 语句的 WHERE CURRENT OF 子句中不能引用游标。该选项优于要更新的游标的默认功能。
      

  2.   

    加上 for update of 列名,还是不行.
      

  3.   

    lz 的算法有问题。
    fetch next 是提取当前位置的数据后,再向后移动一行。因此,在 fetch next 提取最后一行数据后,游标的位置将不再是有效位置,update 当然会无效。最关键的在于此算法无法实现 lz 的要求。如果 select ID,address from tab  的结果集不是按 address 列排序,即相同的 address 列值不相邻,游标将无法为 address 列相同的记录分配相同的 id 值。另外,fetch next 后,update 更新不是当前行的数据,而是下一行的数据。其实,可以直接用 update 语句就可以直接更新,
    ;with cte as(
    select id,dr=DENSE_RANK() over (order by address) from tab
    )
    update tab set tab.id=cte.dr from tab,cte where tb.id=cte.id;
      

  4.   

    这个例子中,把scroll去掉就可以运行了