存储过程的递归调用(树形结构路径的快速生成)
Posted 丰兰月
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了存储过程的递归调用(树形结构路径的快速生成)相关的知识,希望对你有一定的参考价值。
最近在做表数据整理的时候碰到这样的一个问题,我有一张permission表,其数据结构为树形结构,里面有个permission_path字段用于记录根节点到父节点的路径(以permission_id为路径)。
例子:假设100的父节点为10,10的父节点为1,这100的路径为:1/10。
但现在有个问题,permission_path字段在当时并没有处理(为空字符串),如今这个表有四五百条数据,写代码来改太麻烦,更别说一条条数据手动修改,不可行!
能否通过一个语句块来自动生成路径?显然是可以的,因为现在的oracle、SQL SERVER2005以上版本和mysql5.0以上版本的数据库都支持存储过程,而存储过程还有个比较有趣的玩法,那就是递归调用!用这个方法就可以快速、方便地解决上述问题。
存储过程的概念这里就不介绍了,语句非常简单,直接上语句(我使用的数据库是mysql5.6),一步步解析:
CREATE PROCEDURE test(IN parent int) BEGIN DECLARE ids VARCHAR(255) DEFAULT ‘0‘; DECLARE IND INT; DECLARE i INT DEFAULT 1; DECLARE path VARCHAR(255); SELECT GROUP_CONCAT(t.permission_id) INTO ids from system_permissions t where t.permission_parent = parent; SELECT COUNT(t.*) INTO IND from system_permissions t where t.permission_parent = parent; SELECT t.permission_path INTO path from system_permissions t where t.permission_id = parent; if ids <> ‘0‘ THEN UPDATE system_permissions set permission_path = CONCAT(path,‘/‘,parent) where permission_parent = parent; SET @@max_sp_recursion_depth = 100; while i <= IND DO call test(substring_index(substring_index(ids,‘,‘, i), ‘,‘, -1)); set i = i + 1; end while; end if; end
先介绍基本语法:
create procedure test(IN p1 int,IN p2 varchar2(10)) //create procedure 函数名(IN 参数1 类型,IN 参数2 类型),英文部分为固定写法,
中文部分为自定义,其中类型只能使用数据库存在的类型 begin //标识着存储过程逻辑的开始 语句内容 //逻辑、语句都写在此处 end //标识着存储过程逻辑的结束
DECLARE 声明变量,
DECLARE ids VARCHAR(255) DEFAULT ‘0‘; //DECLARE 表示声明一个变量,该变量类型为varchar(255),默认值为0
把变量都定义好后,就可以使用sql语句对数据进行操作
在几个select语句之后,会看到if的判断语句,在if中使用update更新表的permissiom_path的值
if ids <> ‘0‘ THEN //if语句的开头,if 判断条件 then 逻辑内容
end if; //if语句的结尾
while循环语句,用于循环遍历同级数据,在这个存储过程中也充当条件,避免无限递归循环
while i <= IND DO //while语句的开头,while 判断条件 do 逻辑内容
end while; //while语句的结尾
存储过程的递归调用有两个核心:
1、设置树的极限深度,使用场景一般为存储过程中调用存储过程
SET @@max_sp_recursion_depth = 100; //绝大部分情况设置100就够用了,除非递归调用的深度超过100
2、调用自己
call test(substring_index(substring_index(ids,‘,‘, i), ‘,‘, -1)); //call 存储过程名(参数)
最后,由于我的permission表的树形结构的根节点id是0,所以我在生成存储过程后执行的语句为
call test(0)
这样就可以为permision表中的permission_path字段自动赋上路径值
其实存储过程的用法并不复杂,只要记住格式就行了,固定的格式开头和结尾,中间的逻辑都可以是非常简单的语句。而存储过程的递归调用需要注意的地方无非是树的深度的设置,以及防止死循环的逻辑。对于用代码写过递归调用的朋友们来说这不是什么有难度的事,如果没有写过递归调用这样的逻辑,建议先通过代码熟悉递归调用的特点以及注意事项,再来写sql!
ps:第一次写博客,如有不足的地方欢迎指出!
以上是关于存储过程的递归调用(树形结构路径的快速生成)的主要内容,如果未能解决你的问题,请参考以下文章