讲师中心 微信公众号
AI工具推荐 视频效率加速

MySQL 8.0递归CTE如何避免无限循环

云强小哥_5570

云强小哥_5570

发布时间:2026-08-17 08:13:07

|

877人浏览过

|

来源于php中文网

原创

终止条件必须写在递归成员的WHERE子句里,递归停止的唯一依据是某轮递归查询返回空结果集;若漏写、错写或置于外层SELECT,优化器无法提前截断,将跑满最大递归深度后报错。

mysql 8.0递归cte如何避免无限循环

终止条件必须写在递归成员的 WHERE 子句里

递归停止的唯一依据是“某轮递归查询返回空结果集”,不是靠计数器或时间。如果你把 WHERE 写在最外层 SELECT,或者漏掉、写错条件,优化器根本不会提前截断迭代,而是硬跑满 cte_max_recursion_depth 后报错 ERROR 3636 (HY000): Recursive query aborted after 1001 iterations。

常见错误包括:

  • WHERE n 写成 <code>WHERE n → 多算一轮,可能触发超限
  • 用 st.level <= 5 代替 st.level < 5 → 层级判断边界偏移
  • 锚点查 manager_id = 1001,递归时却用 e.id = st.manager_id(方向反了),导致永远找不到下级,无限循环

数据有环时单靠层级限制不够

树形结构若存在 A→B→C→A 这类自循环,仅靠 level < 5 无法阻止死循环:它可能在第 4 层回到 A,第 5 层又走到 B,第 6 层再进 C……直到撞上限才报错。

MySQL 8.0.28+ 支持路径数组防环,推荐写法:

WITH RECURSIVE dept_tree AS (
  SELECT id, name, parent_id, 1 AS level, CAST(id AS CHAR(1000)) AS path
  FROM departments WHERE parent_id IS NULL
  UNION ALL
  SELECT d.id, d.name, d.parent_id, dt.level + 1,
         CONCAT(dt.path, ',', d.id)
  FROM departments d
  INNER JOIN dept_tree dt ON d.parent_id = dt.id
  WHERE d.id NOT IN (SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(dt.path, ',', nums.n), ',', -1) 
                     FROM numbers nums 
                     WHERE nums.n <= LENGTH(dt.path) - LENGTH(REPLACE(dt.path, ',', '')) + 1)
)

更简洁的做法(8.0.28+):

  • 用 MEMBER OF 判断:WHERE d.id MEMBER OF (JSON_EXTRACT(dt.path, '$')) 不成立才继续
  • 但注意 path 必须存为 JSON 数组,否则需先 JSON_CONTAINS 配合 CAST

递归成员必须放在 JOIN 右侧

MySQL 强制要求递归 CTE 在每轮中只能作为被驱动表(即 JOIN 的右表)。如果写成 FROM dept_tree dt INNER JOIN departments d,会直接报错 ERROR 3641 (HY000): Recursive reference to CTE 'dept_tree' is not allowed in this context。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载

原因在于执行模型:每轮必须以上一轮 CTE 输出为驱动源,去探查基础表。颠倒顺序会导致优化器无法构建迭代链。

  • ✅ 正确:FROM departments d INNER JOIN dept_tree dt ON d.parent_id = dt.id
  • ❌ 错误:FROM dept_tree dt INNER JOIN departments d ON d.parent_id = dt.id
  • ❌ 错误:FROM departments d LEFT JOIN dept_tree dt ON ...(LEFT JOIN 右侧也不允许)

调试阶段务必加 LIMIT,别只调大 cte_max_recursion_depth

MySQL 8.0.19+ 支持在递归 CTE 最终 SELECT 后加 LIMIT,它会在结果行数超限时主动中断,不等迭代跑满。这比盲目调高 cte_max_recursion_depth 更安全、更可控。

比如:

WITH RECURSIVE numbers AS (
  SELECT 1 AS n
  UNION ALL
  SELECT n + 1 FROM numbers WHERE n < 1000
)
SELECT * FROM numbers LIMIT 20;

即使 WHERE 条件写错,也只会返回前 20 行,方便你肉眼确认路径是否异常。生产环境上线前,建议先用 LIMIT 100 跑通逻辑,再逐步放开。

真正难的不是写出语法正确的递归 CTE,而是确保它在线上面对百万节点、脏数据、隐式环时,仍能收敛——这取决于你对数据拓扑的理解,而不是对 SQL 关键字的熟悉程度。

热门AI工具

更多
Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

3863

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

831

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1009

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

5701

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2643

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

5680

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

7481

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1030

2024.04.29

PDF转图片方法
PDF转图片方法

需要把 PDF 页面用于上传、预览、分享或图片归档时,PDF 转图片方法专题整理 JPG/PNG 格式选择、逐页导出、清晰度设置、批量下载和结果检查等流程,帮助用户稳定完成 PDF 图片化处理。

0

2026.09.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 177人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 282人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn