mysql存储过程系列一:递归查询

   项目中需要用到递归查询的功能,所以研究了一下。

 

    首先表的结构如下:

     Table: tb_department


FieldTypeComment
   idbigint(20) NOT NULL机构编号

seq_novarchar(100) NULL机构编码(规则:省级机构:1-9,市级:10-99,县级100-999,网格:大于1000)

parent_seq_nobigint(20) NULL上级机构编码

namevarchar(50) NULL机构名

flagint(1) NULL机构所属的级别(1表示省级,2表示市级,3表示县级,4表示网格级别)

priorityint(4) NULL机构排序

remarksvarchar(500) NULL

备注

 

     只有上面标注为红色的字段会用到,其他的字段不需要用到。这张表存放的是部门的信息,其中parent_seq_no存放的是上级部门的id号(注意不是上级部门的seq_no)。这样就构成了上下级关系,就可以形成递归查询的条件了。

 

    创建表的sql为: 
CREATE TABLE `tb_department` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '机构编号',
  `seq_no` varchar(100) CHARACTER SET utf8 DEFAULT NULL COMMENT '机构编码(规则:省级机构:1-9,市级:10-99,县级100-999,网格:大于1000)',
  `parent_seq_no` bigint(20) DEFAULT NULL COMMENT '上级机构编码',
  `name` varchar(50) CHARACTER SET utf8 DEFAULT NULL COMMENT '机构名',
  `flag` int(1) DEFAULT NULL COMMENT '机构所属的级别(1表示省级,2表示市级,3表示县级,4表示网格级别)',
  `priority` int(4) DEFAULT NULL COMMENT '机构排序',
  `remarks` varchar(500) COLLATE utf8_bin DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  UNIQUE KEY `seq_no_UNIQUE` (`seq_no`),
  UNIQUE KEY `name_UNIQUE` (`name`)
ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='部门表,在组织机构管理中的部门管理的信息存储在这张表中'
  

   表中的数据暂时有如下几行:

idseq_noparent_seq_nonameflagpriorityremarks
11(NULL)湖北省11(NULL)
221武汉市22(NULL)
300012洪山区31000(NULL)
400022青山区310001(NULL)
5100013洪山区网格1410002(NULL)
6100033洪山区网格2410004(NULL)
7100054青山区网格1410006(NULL)
8100074青山区网格2410008(NULL)
1000032江岸区321
11003010一元路网格32223(NULL)
12003210解放大道网格323(NULL)
13003110沿江大道网格312(NULL)
14003310分销渠道网格9999(NULL)

 下面这张图列出了部门的上下级关系:



现在要做的是,给定一个部门的id,查询出他下面所有的子部门。如给定部门id为3,那么需要输出3,5,6

 

需要编写两个存储过程,一个是基础的存储过程,执行递归操作,命名为:findChildList,还有一个是调用该存储过程的存储过程,使用递归存储过程执行后的结果,命名为:findDepList。

 

首先定义执行递归操作的存储过程:findChildList

 CREATE DEFINER = 'root'@'%'
PROCEDURE findChildList(IN departmentId BIGINT)
BEGIN
  DECLARE v_dep         INTEGER DEFAULT -1;
  declare done integer DEFAULT 0;
  DECLARE C_dep CURSOR FOR SELECT d.id
                           FROM
                             tb_department d
                           WHERE
                             d.parent_seq_no = departmentId;
  DECLARE CONTINUE HANDLER FOR NOT found set done=1;
  SET @@max_sp_recursion_depth = 10;
 INSERT INTO tmp_Dep VALUES (departmentId);
  OPEN C_dep;
  FETCH C_dep INTO v_dep;
  WHILE (done =0)
  DO
    CALL findChildList(v_dep);
    FETCH C_dep INTO v_dep;
  END WHILE;
END

 

再定义调用递归操作的存储过程:findDepList

CREATE DEFINER = 'root'@'localhost'
PROCEDURE findDepList(IN departmentId BIGINT)
BEGIN

  DROP TEMPORARY TABLE IF EXISTS tmp_Dep;
  CREATE TEMPORARY TABLE tmp_Dep(
  depId INTEGER
);
  DELETE
FROM
  tmp_Dep;
  CALL findChildList(departmentId);
  SELECT distinct depId
FROM
  tmp_Dep order by depId;
END

 

现在在mysql中创建好这两个存储过程,并且执行 call findDepList(3)就会输出3,5,6

 

临时表是执行递归查询的关键,要想使用存储过程执行后的结果,使用临时表是一种很好的办法,在这个例子中,在主调程序(findDepList)中创建好了临时表tmp_Dep,在被调用程序(findChildList)中往临时表中插入数据,最后在主调程序中可以使用递归查询后的数据。注意:单纯执行findChildList会报语法错误。这样在我们的业务逻辑中如果需要查询一个部门的子部门,只需要将findDepList的代码移植过去,既创建中间表,然后执行存储过程,最后就可以从中间表中查询出需要的结果。

  

 


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 存储过程是一种在 MySQL 数据库中存储并执行 SQL 语句的方法。MySQL 存储过程可以使用递归技术来处理一些需要对同一数据进行多次处理的问题,比如树形结构的遍历、图形结构的遍历等。下面是一个使用 MySQL 存储过程实现递归的示例: 首先,我们需要创建一个表,用于存储树形结构的数据。假设这个表名为 `tree`,包含如下字段: ``` id INT PRIMARY KEY, name VARCHAR(255), parent_id INT ``` 其中,`id` 是节点的唯一标识符,`name` 是节点的名称,`parent_id` 是节点的父节点标识符。如果一个节点没有父节点,则其 `parent_id` 为 NULL。 接下来,我们可以创建一个存储过程,用于从指定的节点开始遍历整个树形结构。这个存储过程包含两个参数:起始节点的 `id` 和当前节点的深度。 ``` CREATE PROCEDURE traverse_tree (IN start_id INT, IN depth INT) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE cur_id INT; DECLARE cur_depth INT; -- 创建一个游标,查询当前节点的所有子节点 DECLARE cur CURSOR FOR SELECT id FROM tree WHERE parent_id = start_id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; -- 遍历所有子节点 OPEN cur; read_loop: LOOP FETCH cur INTO cur_id; IF done THEN LEAVE read_loop; END IF; -- 处理当前节点 SET cur_depth = depth + 1; SELECT CONCAT(REPEAT(' ', depth), name) FROM tree WHERE id = cur_id; -- 递归处理当前节点的子节点 CALL traverse_tree(cur_id, cur_depth); END LOOP; CLOSE cur; END; ``` 这个存储过程使用游标查询当前节点的所有子节点,并递归调用自己处理子节点。它还使用了一个 `depth` 参数,用于记录当前节点的深度,以便输出时缩进一定的空格。 我们可以调用这个存储过程,从指定的节点开始遍历树形结构。 ``` CALL traverse_tree(1, 0); ``` 其中,`1` 是起始节点的 `id`,`0` 是起始节点的深度(根节点的深度为 0)。这个存储过程将会输出整个树形结构的层次结构。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值