mysql -- 递归查询所有子节点

来源:互联网 发布:osi的七层网络结构图 编辑:程序博客网 时间:2024/06/05 16:36

背景

有个需求,查询一个文件中的所有子目录的文件文件夹

实现

1. 数据库设计

首先, 建立一张 t_files 表, 模拟文件树结构。

  create table `t_files` (  id int auto_increment,  file_name varchar(100) default '',  file_type tinyint(4) default 0,  parent_id int null,  update_time timestamp null,  primary key(id),  unique key(file_name, parent_id) );

模拟数据:
这里写图片描述

表中数据对应文件树结构为: 根目录下有两个文件夹, 1个文件; 文件夹1下有一个文件夹3和一个文件;而文件夹3下又有一个文件03。


需求: 如何用sql语句, 递归查询到文件夹1下的所有文件夹及文件?


2. 实现分析

思路
第一步: 先找到文件1下的子目录

select *from t_files where parent_id = 1;

结果:
这里写图片描述

第二步: 找到子目录下文件夹下的子目录
这时候, 我们遇到了两个难点
(1) 子目录下文件夹有多个, 怎么查询?
(2) 子目录下如果还有文件夹, 那么就需要一直循环下去, 什么时候结束?

解决方法
(1) 多个同时查询, 我们需要用到mysql函数;
group_concat(): 多条记录合成一条记录

select group_concat(id) as ids from t_files where parent_id =1;

结果:
这里写图片描述

find_in_set(str, strlist) : 在多条记录中查询特定列
str 要查询的字符串
strlist 字段名 参数以”,”分隔 如 (1,2,6,8)

select group_concat(id) as ids from t_files where find_in_set(parent_id, '1, 4');

结果:
这里写图片描述

(2) 循环如何结束, 需要用mysql FUNCTION 函数。
while id is null
– 自然语言
当所有子目录下没有文件夹就结束

3. mysql 实现完整语句

根据以上思路,我们可以通过以下mysql函数,完成递归查询。

DELIMITER //CREATE FUNCTION `getChildLst`(rootId INT)RETURNS varchar(1000) READS SQL DATABEGIN  DECLARE sTemp VARCHAR(1000);  DECLARE sTempChd VARCHAR(1000);  SET sTemp = '$';  SET sTempChd =cast(rootId as CHAR);  WHILE sTempChd is not null DO    SET sTemp = concat(sTemp,',',sTempChd);    SELECT group_concat(id) INTO sTempChd FROM t_files where FIND_IN_SET(parent_id,sTempChd)>0;  END WHILE;  RETURN sTemp;END  //DELIMITER ;

调动语句:

select *from t_files where find_in_set(id, getChildLst(1));

结果:
这里写图片描述

是的, 我们完成了需求: 查询到文件夹1下的所有文件夹及文件。

4. 效果图

我们应用它,实现了一个h5发布系统, 即可以在线操作文件。 效果如下:
这里写图片描述
这里写图片描述

总结

  1. 文件树结构, 数据库设计采用parent_id 这个字段, 来标识上一级目录。
  2. mysql 中 group_concat() 函数实现多条记录形成一条。
  3. mysql 中 find_in_set() 函数实现在集合中查询。
  4. mysql 中 使用自定义函数 function 可以实现较复杂的功能。
  5. 分享下,h5发布系统技术栈。
    前端: vue2 + element + axios
    后台: node + express + fs-extra + mysql

欢迎一起学习,交流。

阅读全文
1 0