You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何MS SQL中SELECT语句在递归CTE与普通查询中行为不同?

为什么MS SQL中递归CTE的SELECT行为与普通查询不同?

核心原因是递归CTE的执行逻辑和普通查询/UNION ALL查询完全不同,它不是对完整结果集的集合遍历,而是基于迭代的递归生成过程:

1. 普通查询与UNION ALL查询的逻辑

这两种场景都是标准的集合操作:

  • 普通查询会遍历目标表的所有行,执行变量拼接时会逐行更新@txt,最终得到所有值的拼接结果。
  • UNION ALL查询是把两个结果集合并成一个完整的集合,SELECT同样会遍历这个合并后的所有行,行为和普通查询一致。

对应代码示例:

-- 普通查询场景
create table #alpha3 (names varchar(max))
insert into #alpha3 values ('a'), ('aa')
declare @txt varchar(max)
select top 10 @txt = concat(@txt, names, ' ') from #alpha3
select @txt;
-- UNION ALL查询场景
create table #beta (names varchar(max))
insert into #beta values ('a'), ('aa')

select * from (
select * from #beta
union all 
select * from #beta) as aa

2. 递归CTE的执行逻辑

递归CTE由锚点成员和递归成员两部分组成,执行流程是迭代式的:

  1. 先执行锚点成员,生成初始结果行(names='aa', num=0);
  2. 接着执行递归成员,仅基于上一轮递归输出的结果集(而不是整个CTE的所有行)来生成新行——也就是用前一次的names拼接'a',num加1;
  3. 重复步骤2,直到递归成员的WHERE条件(num<10)不满足时停止。

整个过程是逐步生成新行,而不是遍历已有的所有行,所以你看到的是“仅取上一行的最后值递归”的行为。

对应递归CTE代码:

with cte as 
( select cast('aa' as varchar(max)) as names, 0 as num 
  union all 
  select cast (names + 'a' as varchar(max)), num+1 from cte
  where num<10 
  ) 
select * from cte 

内容的提问来源于stack exchange,提问作者Ali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 03:15:48