我正在编写一个Sybase存储过程,其中一个游标从表中获取记录并重新插入记录。令人惊讶的是,我发现fetches看到amd返回记录插入到同一个循环中。在某些情况下,这会导致无限循环,有时循环会结束一些额外记录。浏览Sybase文档我找不到治愈方法。事务隔离没有帮助,因为我们在单个事务中执行操作。当然,我可以通过插入循环中的临时表然后在循环结束后插回主表来解决问题。 但问题仍然存在:如何将光标提取与插入隔离到同一个表? 伪代码如下:
create table t (v int)
go
insert into t(v) values (1)
create procedure p as
begin
declare @v int
declare c cursor for select v from t
begin transaction
open c
while 1=1 begin
fetch c into @v
if (@@sqlstatus != 0) break
insert into t (v) values (@v+1)
end
close c
commit
end
go
exec p
go
答案 0 :(得分:0)
我也对这种行为感到惊讶。游标只迭代行,它们在循环期间不会受到变化的影响。 manual说明了这一点:
对所有页锁定表的搜索或定位更新可能会发生变化 排的位置;例如,如果它更新a的键列 聚集索引。光标不跟踪行;它仍然存在 位于原始位置的下一行之前。 在后续提取返回之前,不允许定位更新 下一行。更新的行可能对光标可见一秒钟 时间,如果行移动到搜索顺序中的稍后位置
我的解决方案是插入临时表并在结尾处复制结果,这也加快了大约10倍的过程。
的伪代码:
select * into #results from OriginalTable where 1<>1 --< create temp table with same columns
WHILE fetch...
BEGIN
insert into #results
select -your-results-here
END
insert into OriginalTable select * from #results