mysql 8.0+ 递归查询唯一原生方案是 with recursive;低于 8.0.1 版本报 error 1064,非配置问题;查子节点时 anchor 与 join 方向须一致(如 d.parent_id = dt.id),方向错误导致空结果或无限循环;error 3636 源于递归未自然终止,主因是自引用、环状结构或缺失 where 终止条件;union all 为强制要求,列数、类型须严格一致;cte 禁止出现在 left join 右侧或子查询中。

MySQL 8.0+ 的递归查询只能靠 WITH RECURSIVE,没有替代方案;低于 8.0.1 版本会直接报错 ERROR 1064 (42000),不是配置问题,是语法不被识别。
查子节点时 anchor 和 JOIN 条件方向必须一致
常见错误是把 parent_id = dt.id 写成 id = dt.parent_id,结果查出来全是空或错层。锚点选的是“起点”,递归部分必须沿着同一方向延伸:
- 查某部门的所有下级:anchor 取
WHERE id = 1,JOIN 条件是d.parent_id = dt.id(子表的 parent_id 指向上一层) - 查某员工的所有上级:anchor 取
WHERE id = 123,JOIN 条件是t.id = p.parent_id(当前行的 parent_id 是上一层的 id) - 方向反了不会报错,但结果集不符合业务逻辑,且容易触发无限循环
递归深度超限报错 ERROR 3636 不是语法错,而是数据或逻辑问题
这个错误本质是迭代轮次达到 cte_max_recursion_depth 上限(默认 1000),说明递归没自然终止。原因通常是:
- 存在自引用:某条记录
parent_id = id - 存在环状结构:A → B → C → A
-
WHERE终止条件漏写或逻辑恒真(比如写成WHERE 1) - 锚点没命中真实数据(
WHERE id = 999但表里没有该 id),此时整个 CTE 返回空——不报错,但后续逻辑可能崩
临时修复可执行 SET SESSION cte_max_recursion_depth = 50 缩小范围快速验证是否真超深;长期需清理脏数据或加 level 显式兜底。
UNION ALL 是硬性要求,列数和类型必须严格对齐
用 UNION 会报错 ERROR 1223 (HY000);更隐蔽的坑是隐式类型转换失败:
- anchor 返回
INT,递归部分算出BIGINT(比如level + 1在大数场景下溢出),导致列类型不一致 - 字符串拼接时未显式
CAST或CONCAT,一边是VARCHAR(20),另一边是TEXT,可能截断或报错 - 推荐在 CTE 声明中显式写出列名和类型,例如
WITH RECURSIVE tree (id, name, parent_id, level) AS (...)
CTE 不能出现在 LEFT JOIN 右侧,也不能嵌套在子查询里
这是 MySQL 特有语法限制,不是逻辑错误:
-
SELECT * FROM users LEFT JOIN dept_tree ON ...会报ERROR 1109 (42S02): Unknown table 'dept_tree' -
WHERE id IN (SELECT id FROM dept_tree)会报Recursive reference to CTE 'dept_tree' is not allowed in subquery - 正确做法是把 CTE 放在最外层
FROM,或先物化结果(CREATE TEMPORARY TABLE),再关联其他表
真正难调的从来不是语法标点,而是 anchor 起点选错、递归方向反了、或者数据里藏着没发现的自环——这些都不会立刻报错,但结果已经不可信了。











