Почему бы не использовать курсор ???
Я должен не согласиться со многими другими ответами, которые вы найдете здесь, на StackOverflow. Как правило, вы увидите, что у людей есть много всего плохого, что можно сказать о курсорах ... и они правы, когда мы говорим о традиционных таблицах ... единственная проблема в том, что ваш вопрос о табличной переменной , которую вы использовать внутри хранимой процедуры.
Ваша первая точка принятия решения всегда должна заключаться в том, чтобы проверить, можете ли вы выполнять операции на основе множеств, а не итерации (построчную обработку). Базы данных оптимизированы для первых. Ответ, который я даю здесь, для тех, кто решил, что они не могут использовать подход на основе множеств и , цель итерации - табличная переменная.
Ваша табличная переменная похожа на коллекцию на языке программирования. Это частная структура в памяти. Нет абсолютно никаких проблем с повторением этого в стиле ForEach, когда вы находитесь внутри хранимой процедуры. Если ваш сценарий действительно требует построчную обработку, то курсор в вашем случае, безусловно, подходит. Я действительно не понимаю, почему нет.
Давайте рассмотрим пример, основанный на вашем сценарии.
Сначала мы определим тип таблицы:
CREATE TYPE [IntListType] AS TABLE
( [T] INT );
GO
Затем мы определяем хранимую процедуру, которая использует эту таблицу в качестве входных данных:
CREATE PROCEDURE [myTest]
(
@IntListInput IntListType READONLY
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @myInt INT;
DECLARE intListCursor CURSOR LOCAL FAST_FORWARD
FOR
SELECT [T]
FROM @IntListInput;
OPEN intListCursor;
-- Initial fetch attempt
FETCH NEXT FROM intListCursor INTO @myInt;
WHILE @@FETCH_STATUS = 0
BEGIN
-- Here we do some kind of action that requires us to
-- process the table variable row-by-row. This example simply
-- uses a PRINT statement as that action (not a very good
-- example).
PRINT 'Int var is : ' + CONVERT(VARCHAR(max),@myInt);
-- Attempt to fetch next row from cursor
FETCH NEXT FROM intListCursor INTO @myInt;
END;
CLOSE intListCursor;
DEALLOCATE intListCursor;
END;
GO
Итак, да, я использую курсор для итерации.
Обратите внимание, что я использую ключевые слова LOCAL
и FAST_FORWARD
только для того, чтобы оптимизатору было ясно (явно), что я не собираюсь обновлять свой курсор, и я буду прокручивать только вперед и буду получать к нему доступ только с в рамках процедуры.
Я проверял это так:
DECLARE @IntList IntListType;
-- Put some random data into our list
INSERT INTO @IntList VALUES (33);
INSERT INTO @IntList VALUES (777);
INSERT INTO @IntList VALUES (845);
INSERT INTO @IntList VALUES (71);
EXEC myTest @IntList;
GO