Я заметил странную вещь внутри хранимой процедуры с помощью select on table variables. Он всегда возвращает значение (на последующих итерациях), которое было выбрано на первой итерации курсора. Вот пример кода, подтверждающий это.Таблица Переменная внутри курсора, странное поведение - SQL Server
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 и пробовал различные комбинации, я заметил, что удаление вершины из следующей строки, дает мне правильные значения из таблицы переменных внутри курсора.
SELECT TOP 1 @outid = LogId FROM @Log;
который сделал бы его как этот
SELECT @outid = LogId FROM @Log;
Я не уверен, что здесь происходит. Я думал, что TOP 1 на переменной таблицы должен работать, полагая, что новая таблица создается на каждой итерации цикла. Может ли кто-то пролить свет на переменную область видимости таблицы и на всю жизнь.
Обновление: У меня есть решение обойти странное поведение здесь. В качестве решения я объявил таблицу вверху цикла и удалив все строки в начале цикла.
Если я правильно прочитал этот код, вы создадите новую таблицу @Log с каждым циклом. Если это так, то @Log всегда имеет только 1 запись !? Какую цель вы хотите достичь, что вы ожидаете и что действительно происходит. До сих пор мне нужно больше разъяснений, чтобы помочь. – YvesR
@YvesR - Вы не читаете его правильно. Это оператор объявления, а не исполняемая строка. Он создается неявно один раз. Код никогда не должен доходить до этой линии. например 'IF (1 = 0) BEGIN DECLARE @T TABLE (X INT) END; SELECT * FROM @T; '(хотя анализатор будет жаловаться, если он встретит ссылку на него до того, как увидит объявление) –
@MartinSmith, вы правы. Спасибо за объяснение. –