SQL 如何用 WITH RECURSIVE 实现图的路径遍历(有向无环图)-SQL

with recursive 递归查询必须显式设置终止条件(如 depth 限制或路径去重),否则 postgresql/sqlite/mysql 8.0+ 均报错;依赖数据自然结束不可靠,需用 array 类型配合 not … any(path) 防环并避免误匹配。

WITH RECURSIVE 递归查询必须有终止条件,否则直接报错

PostgreSQL 和 SQLite 支持 WITH RECURSIVE,但 MySQL 8.0+ 才支持;不加明确的终止逻辑会触发 ERROR: recursive query terminated due to cycle detection 或更常见的 ERROR: stack depth limit exceeded。这不是性能问题,是 SQL 引擎强制的安全限制。

实际写法里,终止靠的是递归成员中对 depth 或路径字符串长度的显式约束,而不是依赖“数据自然结束”。图里没有环 ≠ 查询不会无限递归——比如起点连向自己、或两个节点互相指向,都可能绕过环检测(尤其用字符串拼接路径时)。

  • 必须在递归部分加入 WHERE depth 这类硬限制(根据业务场景调)
  • 推荐用数组记录已访问节点:NOT node_id = ANY(path),比字符串 NOT LIKE 更可靠
  • SQLite 对递归深度默认只允许 1000 层,需运行 PRAGMA recursive_triggers = ON 并设 PRAGMA max_recursive_depth = 2000

构建路径时优先用 ARRAY 而非字符串拼接

用 CONCAT(prev_path, '->', node_id) 看似直观,但会导致无法准确判断是否成环(比如 1->12 会被 '1' 错误匹配),也难做去重和长度统计。PostgreSQL 的 ARRAY 类型天然支持 UNION 去重、@> 包含判断、array_length() 计数。

典型错误是把初始 CTE 的 path 设为 ARRAY[node_id],却在递归部分写成 ARRAY_APPEND(path, next_node) ——这没问题,但若漏掉 DISTINCT ON (node_id),同一节点多次被不同路径抵达时,会重复展开子树,爆炸式增长结果行数。

夏夕资源网专注于CMS网站模板,主流语言整站网站源码下载,网站建设相关教程分享,好用的软件素材整合下载,提供一站式便捷自助服务。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"zy.lucklyus.top",如遇到无法解压的请联系管理员!
夏夕资源网-网站模板_免费源码_资源素材 » SQL 如何用 WITH RECURSIVE 实现图的路径遍历(有向无环图)-SQL
在线时间:12:00 - 22:00
关注微信公众号:微信公众号
站长邮箱:[email protected]
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023659+
  • 本周更新: 0+
  • 最后更新: 2026-03-16

本站指数

×
  • 运营天数: 1393+
  • 资源总数: 47989+
  • 用户总数: 1+
  • 今日更新: 0+
  • 访问次数: 4023659+
  • 本周更新: 0+
  • 最后更新: 2026-03-16