在 SQL Server 中使用 Transact-SQL 循环访问结果集

本文介绍可用于在 SQL Server 中使用 Transact-SQL 循环访问结果集的各种方法。

原始产品版本:SQL Server
原始 KB 数: 111401

总结

本文介绍可用于在存储过程、触发器或 Transact-SQL 批处理中模拟类似 FETCH-NEXT 游标的逻辑的各种方法。

使用 Transact-SQL 语句循环访问结果集

下面是使用 Transact-SQL 语句循环访问结果集的三种方法。 以下示例使用 AdventureWorks 示例数据库中的 Production.Product 表

一种方法是使用临时表。 使用此方法,可以创建初始 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)