出门莫恨无人随,书中车马多如簇。这篇文章主要讲述MYSQL8.019 CTE 递归查询怎么解决死循环三种方法相关的知识,希望能为你提供帮助。
【MYSQL8.019 CTE 递归查询怎么解决死循环三种方法】
mysql CTE 是8.0 引入的SQL 查询的一种功能,通过CTE 可以将复杂的SQL 变得简单,便于分析和查询.
其中CTE 有一种功能递归,
并且牵扯到递归就会有一个问题的提出,就是无限递归的问题.
下面是一个递归死循环的例子
这里先解释一下CTE 递归
1
递归查询至少包含两个子查询, 第一个查询的目的是设置递归的初始值
2
第二个查询成为递归查询,第二个查询调用第一个查询的结果,然后开始循环
之间通过union
all 来连接.
递归查询中,当查询的结果不匹配,或超过了递归次数就会停止.
或者在执行是系统发现是死循环则会在设定好的最大cte_max_recursion_depth 后终止查询.
递归查询中出现3636的问题,分为两种
1
数据出现问题 (这是引起递归出现问题的常见原因)
2
SQL 递归的撰写有问题
根据1 出现问题的概率比较大,并且比较难以排查, 这里就需要在写SQL 的时候,添加一些语句来避免递归出现问题.
1
方法一, 使用distinct ,通过在union 后面添加distinct 来将重复的数据去掉,大部分死循环是因为有重复的数据,这样可以查出数据. 但问题是在 WORKBENCH 中是可以的,但将语句在
MYSQL
程序中是报错的,这点我也没法解释.
2
方法 在MYSQL 8.109 引入了 LIMIT 语句,通过LIMIT 来限制输出数据的数量,投机取巧的避免了部分 3636 的错误
这个方式在workbench 和
MYSQL
命令符下都是OK 的.
实际当中,可能用的最多的是另外一种方式,自动设置让死循环结束
WITH RECURSIVE cte_all AS
(
SELECT dname AS Child
FROM cte_test
WHERE rname=Tim
UNION all
SELECT r.dname
FROM cte_test r, cte_all d
WHERE r.rname=d.Child
)
SELECT /*+ MAX_EXECUTION_TIME(1000) */ * FROM cte_all;
这样的写法在workbench 是OK 的,但在MYSQL 命令行中是还是不可以
当然绕来绕去,最关键的还是修复导致死循环的数据
在修复数据后,在此执行查询,问题解决.
以上几种方法,各有利弊,在软件开发中也有递归函数,当然现在开发的过程中好像在规避递归类似的算法. 但在SQL 的撰写中如果业务逻辑合适, 递归会将SQL 写的比较简单,但需要给定的数据要符合一定的规律,以上的方式均是想通过一定方式来规避由于数据问题,产生的递归问题.
推荐阅读
- #云原生征文#Kubernetes工作负载
- PostgreSQL postgresql 读书会 一期5 优化数据库的参数们
- POSTGRESQL如何存储树形数据 处理树形数据
- 基于eBPF的云原生可观测性开源项目Kindling之Dubbo2 协议开发流程
- postgresql读书会 一期系统管理的一些script3
- MYSQL默认情况下 MYSQL 是ACID 吗?
- #导入Word文档图片# VM虚拟机网络设置
- TIDB 学习计划--- 什么是分布式数据库和TIDB 整体架构
- MYSQL 8VSMYSQL 5.7 到底ORACLE是怎么想的()