mysql 5.7 不支持 with recursive,会报 error 1064 语法错误;替代方案有路径枚举、闭包表、存储过程+临时表,但均存在性能或维护缺陷,根本原因是缺乏递归执行计划优化和物化中间结果能力。

WITH RECURSIVE 在 MySQL 5.7 中根本不可用,不是“难”,是直接报错。
MySQL 直到 8.0.1 才原生支持递归 CTE。你在 5.7 里写 WITH RECURSIVE,会立刻触发 ERROR 1064 (42000): You have an error in your SQL syntax——这不是你语法写错了,是解析器压根不认识这个关键字。
MySQL 5.7 里强行写递归查询会怎样?
常见错误现象包括:
- 执行
WITH RECURSIVE语句时直接报ERROR 1064(语法错误) - 误以为能用存储过程递归调用自己,结果触发
ERROR 1424 (HY000): Recursive stored functions and triggers are not allowed - 用用户变量模拟层级时,遇到多行结果就失效(变量只能存单值),或并发下变量被覆盖
- 自连接写到第 3 层就得硬编码
JOIN,层级一变就要重写 SQL
5.7 真实可用的替代方案只有这几种
没有银弹,每种都有明确代价:
-
路径枚举:字段存类似
/1/3/8/的字符串,查子树用WHERE path LIKE '/1/3/%'。读快,但插入/移动节点要更新所有后代的path,且无法用索引高效前缀匹配(除非加生成列+索引) -
闭包表:额外建一张
tree_closure表,预存所有祖先-后代对。查起来快,但每次增删节点都要批量写多行,事务和维护成本高 -
存储过程 + 临时表 + WHILE 循环:手动展开递归逻辑。必须建
CREATE TEMPORARY TABLE,每次循环用INSERT INTO ... SELECT追加下一层,并用NOT IN (SELECT id FROM temp_result)防重复——漏掉这个就会死循环
为什么这些方案在 5.7 里性能容易崩?
根本原因在于缺乏查询优化器对递归模式的认知:
- 临时表方案每轮循环都走一次全表扫描找子节点,没利用好
parent_id索引(尤其当WHERE parent_id IN (...)的右值列表变长时) - 路径枚举的
LIKE '/a/b/%'无法用普通 B-tree 索引做范围扫描,除非用GENERATED COLUMN + INDEX(5.7 支持生成列,但得手动建) - 闭包表的写放大严重:一个节点挪动位置,可能要删/插上百行
tree_closure记录











