mysql5.0自定义存储过程实现递归

mysql8.0以上才有查询树形结构数据的递归函数RECURSIVE,比如需求是查询一张树形结构表的级别名称上下层级关系路径:

WITH RECURSIVE subordinates AS (
  SELECT id, region_name, parent_id, CAST(region_name AS CHAR(200)) AS path
  FROM mr_industry_region
  WHERE parent_id  = -1 and id = 67652
    UNION all 
  SELECT e.id, e.region_name, e.parent_id, CONCAT(s.path, '/', e.region_name)
  FROM mr_industry_region e
  JOIN subordinates s ON e.parent_id = s.id
)
SELECT id, region_name, path
FROM subordinates;

图中红色的部分替换为需要查询的表即可,字段也根据需要替换

核心字段是id,parent_id

region_name则是级别名称字段

subordinates是递归中用到的临时表的别名,可随意替换

以上sql查询的结果如下

可以看到mysql8.0以上借助函数RECURSIVE实现递归查询还是比较简单的

8.0以下要想完全通过sql实现递归查询,则需要通过存储过程来实现,使用游标实现递归向下查询

实现递归的存储过程如下

CREATE PROCEDURE get_tree_recursive(IN current_id INT, IN inputLevel INT,IN path VARCHAR(255))
BEGIN
    -- 自定义结束标志
    DECLARE done BOOLEAN  DEFAULT FALSE;
    -- 自定义游标赋值变量
    DECLARE currentId INT;
    DECLARE regionName varchar(255);
    DECLARE parentId INT;
    DECLARE curLevel INT;
    -- 自定义游标
    DECLARE cur CURSOR FOR
        SELECT id, region_name, parent_id,level
        FROM mr_industry_region
        WHERE parent_id = current_id and level = inputLevel;

    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;

        -- 创建临时表
    CREATE TEMPORARY TABLE IF NOT EXISTS temp_mr_industry_region
    (
        id        INT PRIMARY KEY,
        region_name   VARCHAR(255),
        parent_id INT,
                path   VARCHAR(255),
        level     INT
    );

    OPEN cur;

    read_loop:
    LOOP
        FETCH cur INTO currentId, regionName, parentId, curLevel;
        IF done THEN
            LEAVE read_loop;
        END IF;
        INSERT INTO temp_mr_industry_region (id, region_name, parent_id, path,level)
        VALUES (currentId, regionName, parentId,concat(path,'/',regionName), curLevel);
        CALL get_tree_recursive(currentId, inputLevel + 1,concat(path,'/',regionName));
    END LOOP;

    CLOSE cur;

END;

 这个存储过程实现了递归调用,其中level字段是层级字段,没有的话可以删除,参数也一并删除即可,region_name对应的还是级别名称,替换为自己的表级别名称字段

CREATE PROCEDURE get_tree()
BEGIN
    -- 自定义结束标志
    DECLARE done BOOLEAN DEFAULT FALSE;
    -- 自定义游标赋值变量
    DECLARE currentId INT;
    DECLARE regionName varchar(255);
    DECLARE parentId INT;
    DECLARE curLevel INT;
    -- 自定义游标,查询所有首级进行游标循环
    DECLARE cur CURSOR FOR
        SELECT id, region_name, parent_id, level
        FROM mr_industry_region
        WHERE parent_id = -1;-- 自行修改条件


    DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = true;
        

    OPEN cur;
    read_loop:
    LOOP
        FETCH cur INTO currentId, regionName, parentId, curLevel;
        IF done THEN
            LEAVE read_loop;
        END IF;
        INSERT INTO temp_mr_industry_region (id, region_name, parent_id,path, level)
        VALUES (currentId, regionName, parentId,regionName, curLevel);
        CALL get_tree_recursive(currentId, curLevel + 1,regionName);
    END LOOP;
    CLOSE cur;
END;
 

这个存储过程get_tree()是递归的启动入口,主要是把首层级查询出来,再调用实现递归的存储过程get_tree_recursive()

执行语句如下:

set SESSION max_sp_recursion_depth=20;

call get_tree();

第一句是mysql要求的递归设置层级深度,session是只在当前sql会话窗口有效,全局的则替换为global,同时账号也需要最高权限,set SESSION max_sp_recursion_depth=20; 我这里设置的是20,不设置默认是0,存储过程无法执行。

第二句则是开始调用存储过程

执行完毕后查看临时表temp_mr_industry_region

注意:level字段如果没有,则把两个存储过程和level有关的字段,参数,游标变量等都 删除,重新执行存储过程即可,数据只能生成一次,重复生成报错。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值