Поделиться через


Итерацию с помощью результирующих наборов с помощью Transact-SQL в SQL Server

В этой статье описаны различные методы, которые можно использовать для итерации результирующих наборов с помощью Transact-SQL в SQL Server.

Исходная версия продукта: SQL Server
Исходный номер базы знаний: 111401

Итоги

В этой статье описаны различные методы, которые можно использовать для имитации логики курсора FETCH-NEXT в хранимой процедуре, триггере или пакете Transact-SQL.

Использование инструкций Transact-SQL для итерации с помощью результирующих наборов

Ниже приведены три метода, которые можно использовать для итерации с помощью результирующих наборов с помощью инструкций Transact-SQL. В приведенных ниже примерах используется таблица Production.Product из примера базы данных AdventureWorks

Одним из методов является использование временных таблиц. С помощью этого метода создается моментальный снимок начальной SELECT инструкции и используется в качестве основы для курсора. Например:

/********** example 1 **********/
SET NOCOUNT ON
DROP TABLE IF EXISTS #MYTEMP 
DECLARE @ProductID int

SELECT * INTO #MYTEMP FROM Production.Product

SELECT TOP(1) @ProductID = ProductID FROM #MYTEMP

WHILE @@ROWCOUNT <> 0
BEGIN
    SELECT * FROM #MYTEMP WHERE ProductID = @ProductID
    DELETE FROM #MYTEMP WHERE ProductID = @ProductID
    SELECT TOP(1) @ProductID = ProductID FROM #MYTEMP
END

Второй метод — использовать min функцию для пошаговой работы по одной строке. Этот метод перехватывает новые строки, добавленные после начала выполнения хранимой процедуры, при условии, что новая строка имеет уникальный идентификатор больше текущей строки, обрабатываемой в запросе. Рассмотрим пример.

/********** example 2 **********/
SET NOCOUNT ON
DROP TABLE IF EXISTS #MYTEMP 
DECLARE @ProductID int

SELECT @ProductID = min( ProductID ) FROM Production.Product
WHILE @ProductID IS NOT NULL

BEGIN
    SELECT * FROM Production.Product WHERE ProductID = @ProductID
    SELECT @ProductID = min( ProductID ) FROM Production.Product WHERE ProductID > @ProductID
END

Примечание.

В примере 1 и 2 предполагается, что для каждой строки в исходной таблице существует уникальный идентификатор. В некоторых случаях уникальный идентификатор не может существовать. Если это так, можно изменить метод временной таблицы, чтобы использовать только что созданный ключевой столбец. Например:

/********** example 3 **********/
SET NOCOUNT ON
DROP TABLE IF EXISTS #MYTEMP 

SELECT NULL AS mykey, * INTO #MYTEMP FROM Production.Product

UPDATE TOP(1) #MYTEMP SET mykey = 1

WHILE @@ROWCOUNT > 0
BEGIN
    SELECT * FROM #MYTEMP WHERE mykey = 1
    DELETE FROM #MYTEMP WHERE mykey = 1
    UPDATE TOP(1) #MYTEMP SET mykey = 1
END

Ссылки

ROW_NUMBER (Transact-SQL)