我在表变量上使用 select 的存储过程中观察到一个奇怪的事情。它总是返回在游标的第一次迭代中获取的值(在后续迭代中)。这是一些证明这一点的示例代码。
DECLARE @id AS INT;
DECLARE @outid AS INT;
DECLARE sub_cursor CURSOR FAST_FORWARD
FOR SELECT [TestColumn]
FROM testtable1;
OPEN sub_cursor;
FETCH NEXT FROM sub_cursor INTO @id;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @Log TABLE (LogId BIGINT NOT NULL);
PRINT 'id: ' + CONVERT (VARCHAR (10), @id);
INSERT INTO Testtable2 (TestColumn)
OUTPUT inserted.[TestColumn] INTO @Log
VALUES (@id);
IF @@ERROR = 0
BEGIN
SELECT TOP 1 @outid = LogId
FROM @Log;
PRINT 'Outid: ' + CONVERT (VARCHAR (10), @outid);
INSERT INTO [dbo].[TestTable3] ([TestColumn])
VALUES (@outid);
END
FETCH NEXT FROM sub_cursor INTO @id;
END
CLOSE sub_cursor;
DEALLOCATE sub_cursor;
但是,当我在 SO 上发布代码并尝试各种组合时,我观察到从下面的行中删除 top 会给我在游标内的表变量中的正确值。
SELECT TOP 1 @outid = LogId FROM @Log;
这会让它像这样
SELECT @outid = LogId FROM @Log;
我不确定这里发生了什么。我认为表变量上的 TOP 1 应该可以工作,认为循环的每次迭代都会创建一个新表。有人可以阐明表格变量范围和生命周期。
更新:我有解决方案来规避这里的奇怪行为。作为一种解决方案,我在循环之前在顶部声明了表格,并在循环开始时删除了所有行。