如何从 CTE 循环访问结果集?

How to loop through result set from a CTE?

提问人:Michał Gałecki 提问时间:11/1/2023 最后编辑:Joel CoehoornMichał Gałecki 更新时间:11/1/2023 访问量:59

问:

我的 SELECT 有问题,我收到错误

消息 208,级别 16,状态 1,第 18
行 对象名称“列表”无效。

怎么了?

DECLARE @end datetime = getdate(),
    @start datetime = CAST('01/01/2023' as datetime),
    @counter INT,
    @MaxId INT, 
    @name NVARCHAR(100);

WITH list as (
    SELECT  DISTINCT ROW_NUMBER() OVER( ORDER BY KodDokumentu) as id, KodDokumentu
    FROM [dbo].[view_list]
    WHERE IdMagazynu = 15 and IdStatusu >= 50 and DataZatw >= @start and DataZatw <= @end
    GROUP BY KodDokumentu
)
SELECT @counter = min(id) , @MaxId = max(id) 
FROM list

WHILE(@counter IS NOT NULL AND @counter <= @MaxId)
BEGIN
    SELECT @name = KodDokumentu
    FROM list WHERE id = @counter

    PRINT CONVERT(VARCHAR,@counter) + '. kod dokumentu ' + @name 
    SET @counter  = @counter  + 1        
END

我想用 CTE 开始一个循环。 命令只是示例。PRINT

t-sql while-loop 公用表表达式

评论

0赞 Luuk 11/1/2023
请附上表格的样本(参见:DBFIDDLEview_list )
1赞 Luuk 11/1/2023
但是:不能在 SELECT 语句中使用.....因此,您可能希望添加有关您正在尝试解决的问题的更多信息......WHILE
0赞 Patrick Hurst 11/1/2023
仅凭您提供的内容,您是否遇到了问题?默认情况下,您只能递归 100 次。您可以使用 1 到 32767 之间的数字作为定义的递归数或 0 来更改此行为,这将允许无限制的递归。这是潜在的危险,因为您的查询可能会消耗所有可用的资源,并破坏实例的稳定性。MAXRECURSIONOPTION (MAXRECURSION n)
3赞 Thom A 11/1/2023
顾名思义,CTE(公共表表达式)是一个表达式,而不是一个对象。它只能在声明它的语句中引用。你所拥有的就像在做,并期望第二句话知道什么是;它不会SELECT SomeValue AS SomeColumn FROM dbo.MyTable; SELECT SomeColumn;SomeColumn
0赞 Stu 11/1/2023
是的,这只是对常见表表达式的误解。如果需要保留数据,则需要使用表变量或临时表,而不是 cte。

答:

0赞 George Menoutis 11/1/2023 #1

您的 CTE 对应于以下内容:select

SELECT @counter = min(id) , @MaxId = max(id) 
FROM list

它不再存在超过这个 SELECT。[list] 在任何后续查询中都不存在。

一个想法是放入一个 #temp 表中,重新读取变量,然后继续使用相同的代码:

--stays the same
WITH list as (SELECT  DISTINCT ROW_NUMBER() OVER( ORDER BY KodDokumentu) as id, KodDokumentu
FROM [dbo].[view_list]
where IdMagazynu = 15 and IdStatusu >= 50 and DataZatw >= @start and DataZatw <= @end
group by KodDokumentu)

-- change to select INTO
SELECT *
into #list
FROM list

--rerun variable assignments
SELECT @counter = min(id) , @MaxId = max(id) 
FROM #list


-- the rest of the while loop stays the same
WHILE(@counter IS NOT NULL....

评论

0赞 Michał Gałecki 11/7/2023
它有效,谢谢!