MySQL递归CTE带LIMIT的特殊语法工作原理解析
关于MySQL递归CTE中LIMIT用法的疑问
常规递归CTE写法
MySQL中常见的递归CTE写法如下:
WITH RECURSIVE cte AS ( SELECT 1 id UNION ALL SELECT id + 1 FROM cte WHERE id < 1000 ) SELECT COUNT(*) FROM cte;
该写法在MySQL官方参考手册中有详细说明。
带LIMIT的替代写法
但使用另一种包含LIMIT的CTE语法,也能得到相同的输出结果:
WITH RECURSIVE cte AS ( SELECT 1 id UNION ALL SELECT id + 1 FROM cte LIMIT 1000 ) SELECT COUNT(*) FROM cte;
这种写法并未在官方参考手册中提及,且和手册里的描述存在矛盾:
递归部分的每次迭代仅处理上一次迭代生成的行。如果递归部分包含多个查询块,各查询块的迭代顺序未指定,每个查询块处理的行要么来自其自身上一次迭代,要么来自自该迭代结束以来其他查询块生成的行。
按照常规逻辑,这个递归部分每次迭代都会生成一行,且没有任何条件会终止下一次递归,但实际递归却会终止,最终总行数和LIMIT指定的数值完全一致。
请问这种语法形式下,MySQL的递归CTE是如何工作的?
更新补充
有评论指出:
原因是LIMIT作用于整个UNION语句,而非单个查询(除非使用括号)。——lemon
这个解释看似合理,但在官方参考手册中找不到关于“LIMIT作用于整个UNION结果集”的相关描述。
另外还有一个疑问点:如果递归终止是因为第1001行生成后被LIMIT丢弃,那么这一行不会触发新的递归生成,从而终止递归,但目前找不到明确说明,为何最后一次迭代生成的行会被LIMIT确定性丢弃。
内容的提问来源于stack exchange,提问作者Akina
相关产品推荐
相关产品推荐

