请参阅以下代码:
declare @crimeurn varchar(20)
DECLARE @finalresults TABLE (crime_urn varchar(20))
DECLARE @potentialresults TABLE (crime_urn varchar(20))
insert into @finalresults values ('1')
DECLARE finalresults_cursor CURSOR FOR
SELECT crime_urn FROM @finalresults
OPEN finalresults_cursor
FETCH NEXT FROM finalresults_cursor INTO @crimeurn
WHILE @@FETCH_STATUS = 0
BEGIN
print @crimeurn
INSERT INTO @finalresults
values ('2')
FETCH NEXT FROM finalresults_cursor INTO @crimeurn
END
select * from @finalresults --line 16
CLOSE finalresults_cursor
DEALLOCATE finalresults_cursor
第16行在SQL工作室管理器中显示5137或12,342行(随机变化)。我期望TSQL导致无限循环,因为在游标的每次迭代中都会插入表变量。
为什么它不会导致无限循环?即为什么返回5,137或12,342行。
答案 0 :(得分:3)
您正在插入堆中。
堆是无序的。没有特别保证在当前行之后插入行并在下一次获取时拾取。
我对您的测试框架稍作修改,并添加了IDENTITY列。在我的情况下,在终止之前它排到了592,353行。
正如您从下面的结果中看到的那样,最后一行恰好被插入文件的前一页(从1623跳到184),因此从倒数第二行开始的分配有序扫描无法找到它。
重现的代码。
declare @crimeurn varchar(20)
DECLARE @finalresults TABLE (crime_urn varchar(20), ID int identity)
DECLARE @potentialresults TABLE (crime_urn varchar(20))
insert into @finalresults values ('1')
DECLARE finalresults_cursor CURSOR FOR
SELECT crime_urn FROM @finalresults
OPEN finalresults_cursor
FETCH NEXT FROM finalresults_cursor INTO @crimeurn
WHILE @@FETCH_STATUS = 0
BEGIN
print @crimeurn
INSERT INTO @finalresults
--OUTPUT INSERTED.ID
values ('2')
FETCH NEXT FROM finalresults_cursor INTO @crimeurn
END
select *, sys.fn_PhysLocFormatter(%%physloc%%) from @finalresults --line 16
ORDER BY ID
CLOSE finalresults_cursor
DEALLOCATE finalresults_cursor
答案 1 :(得分:0)
编辑:下面的信息是错误的,但我已经离开了,因为我认为这是所谓的工作方式。
默认情况下,游标不会以INSENSITIVE
或STATIC
模式运行。默认情况下,游标为DYNAMIC
和OPTIMISTIC
。游标上的documentation没有提到动态游标相对于INSERTS
的行为方式。 INSERT
行为似乎没有记录。
您可以使用SCROLL_LOCKS
选项解决此问题,这样可以保证订单保存。
因为运行
时光标的定义是固定的DECLARE finalresults_cursor CURSOR FOR
SELECT crime_urn FROM @finalresults
在那之后它是静止的。更新表变量@finalresults
不会更改游标finalresults_cursor
。
就是这样:
X = 10
Y = X
X = 20
PRINT X, Y
输出:
20 10
答案 2 :(得分:0)
但是,如果你不关心或不知道光标的类型,你可以使用循环内的@@CURSOR_ROWS
做一些"光标"逻辑:)。
Here是关于@@CURSOR_ROWS
变量可能具有的值的一些文档,具体取决于游标的类型:。