在CURSOR中使用WITH关键字时观察到一些奇怪的行为:
WITH minuteList (aMinute) AS
(
SELECT @startTime UNION ALL
SELECT DATEADD(MINUTE, 1, aMinute)
FROM minuteList
WHERE aMinute < DATEADD(MINUTE, 9, @startTime)
)
SELECT * FROM minuteList
上面的代码可以很好地创建一个包含一个aMinute列的表和一个间隔为1分钟的10个日期时间行。但是,下面的代码进入无限循环,只能无限地打印@startTime值。
DECLARE cursor1 CURSOR FOR
WITH minuteList (aMinute) AS
(
SELECT @startTime UNION ALL
SELECT DATEADD(MINUTE, 1, aMinute)
FROM minuteList
WHERE aMinute < DATEADD(MINUTE, 9, @startTime)
)
SELECT * FROM minuteList
OPEN cursor1
FETCH NEXT FROM cursor1 INTO @laterTime
WHILE @@FETCH_STATUS = 0 BEGIN
PRINT @laterTime
END
CLOSE cursor1;
DEALLOCATE cursor1;
有人可以解释发生了什么以及无限循环发生的原因吗?
答案 0 :(得分:0)
我对游标调用进行了逐行分析,以解释它为什么会进入无限循环。
OPEN cursor1 // Opens your cursor
FETCH NEXT FROM cursor1 INTO @laterTime // Takes the first row returned by the
cursor and inserts it into the
variable @laterTime
WHILE @@FETCH_STATUS = 0 BEGIN // Checks if the next value has been
fetched and executes
the code inside the loop
PRINT @laterTime // Prints the current row
END // Ends the loop when FETCH_STATUS is
not 0 (when fetch fails).
CLOSE cursor1; // Closes the cursor.
无限循环的原因是@@ FETCH_STATUS永远不会被更改,因为您只访问了游标的第一行(获取没有失败,因为它没有被多次调用)。打印@laterTime后,需要获取循环内光标的下一个值。只有当提取失败时,循环才会终止。
将this example视为参考。
修改后的代码如下所示:
OPEN cursor1
FETCH NEXT FROM cursor1 INTO @laterTime
WHILE @@FETCH_STATUS = 0 BEGIN
PRINT @laterTime
FETCH NEXT FROM cursor1 INTO @laterTime
END
CLOSE cursor1;