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

为何含递归CTE的多CTE查询需在首个CTE前加RECURSIVE?

为什么包含递归CTE的多CTE查询必须在首个CTE前加RECURSIVE?

核心原因

在MySQL(以及遵循SQL标准的数据库)中,只要查询里包含任意一个递归CTE,整个WITH子句就必须以RECURSIVE开头——不管第一个CTE是不是递归的。这是语法规则的硬性要求,判断依据是整个WITH块是否包含递归CTE,而非单个CTE的类型。

具体解释

你遇到的Error Code: 1146错误,本质是数据库没有识别出这是一个包含递归逻辑的查询:当你不加RECURSIVE时,数据库会把所有CTE都当作普通非递归CTE处理,递归CTE里对自身的引用(比如你的temp_cte2自关联)会被当成查找普通表的操作,自然找不到对应的表,所以抛出“表不存在”的错误。

而加上WITH RECURSIVE后,数据库会进入递归CTE的解析模式,能正确识别出查询中的递归逻辑,包括对递归CTE自身的引用,因此可以正常执行。

示例对比

错误写法(无RECURSIVE)

WITH temp_cte1 AS (
    SELECT id FROM some_table WHERE parent_id IS NULL
),
temp_cte2 AS (
    SELECT id, parent_id FROM temp_cte1
    UNION ALL
    SELECT t.id, t.parent_id FROM some_table t
    JOIN temp_cte2 tc ON t.parent_id = tc.id
)
SELECT * FROM temp_cte2;

此写法会触发1146错误,因为数据库将temp_cte2当作普通表查找,无法识别其递归身份。

正确写法(加RECURSIVE)

WITH RECURSIVE temp_cte1 AS (
    SELECT id FROM some_table WHERE parent_id IS NULL
),
temp_cte2 AS (
    SELECT id, parent_id FROM temp_cte1
    UNION ALL
    SELECT t.id, t.parent_id FROM some_table t
    JOIN temp_cte2 tc ON t.parent_id = tc.id
)
SELECT * FROM temp_cte2;

这里尽管temp_cte1是非递归的,但整个WITH块因包含temp_cte2这个递归CTE,必须以RECURSIVE开头,数据库才能正确解析递归逻辑。

总结

一句话概括:只要查询中存在递归CTE,整个WITH子句就必须带RECURSIVE关键字,这是SQL语法的规定,和第一个CTE是否递归无关。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:25:00