一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

MySQLWithRecursive与语法结构详解(最新推荐)

时间:2026-06-17 08:46:55 编辑:袖梨 来源:一聚教程网

一、什么是 WITH RECURSIVE

WITH RECURSIVE 是 MySQL 提供的一种递归公共表表达式(Recursive Common Table Expression,Recursive CTE)

MySQLWithRecursive及语法结构详解(最新推荐)

简单理解:

它允许 SQL 自己调用自己,实现递归查询。

类似于 Java 中:

public void test(Node node){    test(node.getChild());}

SQL 以前无法直接递归,只能:

  • 多次自关联(JOIN)
  • 应用层循环查询
  • 存储过程递归

WITH RECURSIVE 出现后,可以直接在 SQL 中完成树形结构遍历。

二、MySQL 从哪个版本开始支持?

MySQL 从:

MySQL 8.0

开始正式支持:

  • CTE(公共表表达式)
  • Recursive CTE(递归公共表表达式)

即:

WITH ...

WITH RECURSIVE ...

都是 MySQL 8.0 新增的特性。

MySQL 5.7 及以前:

❌ 不支持

三、它解决了什么问题

开发中经常出现树形结构:

组织架构

董事长 ├── 总经理 │    ├── 技术部 │    └── 财务部 └── 人事部

菜单系统

系统管理 ├── 用户管理 ├── 角色管理 └── 权限管理

行政区划

中国 ├── 北京 ├── 上海 └── 广东      ├── 深圳      └── 广州

评论回复

评论1 ├── 回复1 │    └── 回复2 └── 回复3

以前查询:

查询所有子节点

需要:

select * from dept where parent_id=1;select * from dept where parent_id in(...);select * from dept where parent_id in(...);

不断循环。

现在:

WITH RECURSIVE

一条 SQL 搞定。

四、WITH RECURSIVE 语法结构

标准语法:

WITH RECURSIVE cte_name AS (    -- 初始查询(锚点查询)    SELECT ...    UNION ALL    -- 递归查询    SELECT ...    FROM table t    JOIN cte_name c      ON ...)SELECT * FROM cte_name;

五、递归执行过程

例如:

WITH RECURSIVE nums AS (    SELECT 1 AS n    UNION ALL    SELECT n + 1    FROM nums    WHERE n < 5)SELECT * FROM nums;

执行步骤:

第一步

执行锚点查询

SELECT 1

结果:

1

第二步

带入递归部分

1 + 1

得到:

2

第三步

继续递归

345

结果:

12345

六、WITH RECURSIVE 的组成部分

必须包含两部分:

1. Anchor(锚点)

递归起点

SELECT 1

2. Recursive(递归部分)

不断调用自身

SELECT n+1FROM numsWHERE n<5

3. UNION ALL

连接两部分

AnchorUNION ALLRecursive

七、第一个实战:生成数字序列

生成1~10

WITH RECURSIVE nums AS (    SELECT 1 AS num    UNION ALL    SELECT num + 1    FROM nums    WHERE num < 10)SELECT * FROM nums;

结果:

12345678910

八、生成日期序列

生成最近7天

WITH RECURSIVE dates AS (    SELECT CURDATE() AS dt    UNION ALL    SELECT DATE_SUB(dt,INTERVAL 1 DAY)    FROM dates    WHERE dt > CURDATE()-INTERVAL 6 DAY)SELECT * FROM dates;

结果:

2026-06-152026-06-142026-06-13...

九、树形结构实战

部门表

CREATE TABLE dept(    id INT PRIMARY KEY,    dept_name VARCHAR(50),    parent_id INT);

数据:

1 总公司 NULL2 技术中心 13 财务中心 14 开发部 25 测试部 26 Java组 47 前端组 4

数据结构

总公司(1)├── 技术中心(2)│    ├── 开发部(4)│    │    ├── Java组(6)│    │    └── 前端组(7)│    └── 测试部(5)└── 财务中心(3)

十、递归向下查询(查询所有子节点)

查询部门1下面所有节点

WITH RECURSIVE dept_tree AS (    SELECT        id,        dept_name,        parent_id,        1 level    FROM dept    WHERE id = 1    UNION ALL    SELECT        d.id,        d.dept_name,        d.parent_id,        dt.level + 1    FROM dept d    JOIN dept_tree dt      ON d.parent_id = dt.id)SELECT *FROM dept_tree;

结果:

1 总公司2 技术中心3 财务中心4 开发部5 测试部6 Java组7 前端组

十一、增加层级显示

WITH RECURSIVE dept_tree AS (    SELECT        id,        dept_name,        parent_id,        1 level    FROM dept    WHERE id=1    UNION ALL    SELECT        d.id,        d.dept_name,        d.parent_id,        dt.level+1    FROM dept d    JOIN dept_tree dt      ON d.parent_id=dt.id)SELECT    id,    dept_name,    levelFROM dept_tree;

结果:

id  dept_name   level1   总公司      12   技术中心    23   财务中心    24   开发部      35   测试部      36   Java组      47   前端组      4

十二、生成完整路径

很多权限系统都这样做。

例如:

总公司/技术中心/开发部/Java组

SQL:

WITH RECURSIVE dept_tree AS (    SELECT        id,        dept_name,        parent_id,        dept_name AS path    FROM dept    WHERE id=1    UNION ALL    SELECT        d.id,        d.dept_name,        d.parent_id,        CONCAT(dt.path,'/',d.dept_name)    FROM dept d    JOIN dept_tree dt      ON d.parent_id=dt.id)SELECT *FROM dept_tree;

结果:

总公司总公司/技术中心总公司/技术中心/开发部总公司/技术中心/开发部/Java组

十三、WITH RECURSIVE 能向上查吗?

答案:

完全可以。

很多人误以为只能向下查。

实际上:

递归方向由 JOIN 条件决定。

十四、向上递归查询祖先节点

例如:

查询 Java组(id=6) 的所有上级。

树:

总公司(1)└── 技术中心(2)     └── 开发部(4)          └── Java组(6)

SQL:

WITH RECURSIVE parent_tree AS (    SELECT        id,        dept_name,        parent_id    FROM dept    WHERE id = 6    UNION ALL    SELECT        d.id,        d.dept_name,        d.parent_id    FROM dept d    JOIN parent_tree pt      ON d.id = pt.parent_id)SELECT *FROM parent_tree;

结果:

6 Java组4 开发部2 技术中心1 总公司

十五、向上生成完整路径

WITH RECURSIVE parent_tree AS (    SELECT        id,        dept_name,        parent_id,        dept_name AS path    FROM dept    WHERE id=6    UNION ALL    SELECT        d.id,        d.dept_name,        d.parent_id,        CONCAT(d.dept_name,'/',pt.path)    FROM dept d    JOIN parent_tree pt      ON d.id=pt.parent_id)SELECT *FROM parent_treeORDER BY id;

最终得到:

总公司/技术中心/开发部/Java组

十六、避免死循环

假设数据错误:

1 -> 22 -> 33 -> 1

形成环:

1↓2↓3↑└───

递归将无限执行。

解决方法:

记录访问路径。

WITH RECURSIVE dept_tree AS (    SELECT        id,        parent_id,        CAST(id AS CHAR(1000)) path    FROM dept    WHERE id=1    UNION ALL    SELECT        d.id,        d.parent_id,        CONCAT(dt.path,',',d.id)    FROM dept d    JOIN dept_tree dt      ON d.parent_id=dt.id    WHERE FIND_IN_SET(d.id,dt.path)=0)SELECT *FROM dept_tree;

十七、递归层数限制

查看:

SHOW VARIABLES LIKE '%recursion%';

通常:

cte_max_recursion_depth = 1000

表示最多递归1000层。

修改:

SET SESSION cte_max_recursion_depth = 5000;

或者:

SET GLOBAL cte_max_recursion_depth = 5000;

十八、WITH RECURSIVE 使用规则总结

必须:

WITH RECURSIVE name AS(    anchor    UNION ALL    recursive)

递归部分必须引用自己

FROM name

必须有终止条件

WHERE level < 100

否则死循环。

推荐使用:

UNION ALL

而不是:

UNION

因为:

UNION

需要去重。

性能更差。

十九、企业开发中的典型应用

组织架构树

总公司 └── 分公司      └── 部门

查询所有下级。

RBAC权限菜单

系统管理 ├── 用户管理 ├── 角色管理 └── 权限管理

加载菜单树。

评论回复

评论 └── 回复      └── 回复

查询完整评论链。

行政区域

中国 └── 广东      └── 深圳

查询省市区。

商品分类

电子产品 └── 手机      └── 安卓手机

查询所有分类。

二十、面试高频问题

Q1:WITH RECURSIVE 从哪个版本开始支持?

MySQL 8.0。

Q2:WITH 和 WITH RECURSIVE 区别?

WITH

普通CTE,不递归。

WITH t AS(  SELECT *  FROM user)SELECT * FROM t;
WITH RECURSIVE

支持递归调用自身。

Q3:能否查询父节点?

可以。

改变 JOIN 方向即可。

向下:

d.parent_id = tree.id

向上:

d.id = tree.parent_id

Q4:为什么推荐 WITH RECURSIVE?

相比循环查询:

  • SQL更简洁
  • 只访问一次数据库
  • 性能更好
  • 天然支持树形结构

总结

WITH RECURSIVE 是 MySQL 8.0 引入的递归查询能力,通过“锚点查询 + UNION ALL + 递归查询”的方式,可以优雅地处理组织架构、菜单树、评论树、行政区划、商品分类等层级数据,既能向下查询所有子孙节点,也能向上查询所有祖先节点,是现代 MySQL 树形数据查询的首选方案。

参考:

mysql递归查询语法WITH RECURSIVE

MySQL RECURSIVE Clauses

MySQL | Recursive CTE (Common Table Expressions)

热门栏目