更新:好的,我能够调试它,发现通过执行该操作,select @@max_sp_recursion_depth我可以看到变量设置为15,但是,当我使用自身运行回调用时CALL single_limb_portfolio_list(xaccount_id, xparent_portfolio_id);,出现错误,指出达到了递归限制0 ,但是它永远不会一次遍历自己”
select @@max_sp_recursion_depth
CALL single_limb_portfolio_list(xaccount_id, xparent_portfolio_id);
当我在下面运行递归存储过程时,即使设置为 SET max_sp_recursion_depth = 15 ;
SET max_sp_recursion_depth = 15 ;
我将这个变量设置在错误的位置吗?它的行为就像永远不会被设置并且始终保持为零?
在此先感谢您的帮助。
递归存储过程:
CREATE DEFINER=`aaron`@`localhost` PROCEDURE `single_limb_portfolio_list`(xaccount_id INT, IN portf_id_in INT, OUT str_portf_list VARCHAR(455)) BEGIN DECLARE xportfolio_ID INT DEFAULT NULL ; DECLARE xp_name INT DEFAULT NULL ; DECLARE xparent_portfolio_id INT DEFAULT NULL ; DECLARE xstr_list VARCHAR(455) ; SET max_sp_recursion_depth = 15 ; SELECT portfolio_id, p_name, parent_portfolio_id FROM portfolio WHERE account_id = xaccount_id AND archived = 0 AND portfolio_id = portf_id_in INTO xportfolio_ID, xp_name, xparent_portfolio_id; IF xportfolio_ID IS NULL /* We have reached the top of the tree and there are no more parents for the portfolio list */ THEN SET str_portf_list = xstr_list; #Set the full tree list to the variable that will be inserted as a row into the temp table previously created ELSE CALL single_limb_portfolio_list(xaccount_id, xparent_portfolio_id); #call the sproc with the next portfolio id to get the next parent id SET xstr_list = concat(xp_name,"->",xstr_list); #Add the portfolio name to the overall portfolio list. Output like: "California -> Los Angelas" END IF; END
这是一个非递归解决方案,您可以根据您的模型进行调整(http://pastie.org/1259300)
drop table if exists product; create table product ( prod_id smallint unsigned not null auto_increment primary key, name varchar(255) not null, parent_id smallint unsigned null, key (parent_id) )engine = innodb; insert into product (name, parent_id) values ('Products',null), ('Systems & Bundles',1), ('Components',1), ('Processors',3), ('Motherboards',3), ('AMD',5), ('Intel',5), ('Intel LGA1366',7); delimiter ; drop procedure if exists product_hier; delimiter # create procedure product_hier ( in p_prod_id smallint unsigned ) begin declare v_done tinyint unsigned default 0; declare v_depth smallint unsigned default 0; create temporary table hier( parent_id smallint unsigned, prod_id smallint unsigned, depth smallint unsigned default 0 )engine = memory; insert into hier select parent_id, prod_id, v_depth from product where prod_id = p_prod_id; /* http://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html */ create temporary table tmp engine=memory select * from hier; while not v_done do if exists( select 1 from product p inner join hier on p.parent_id = hier.prod_id and hier.depth = v_depth) then insert into hier select p.parent_id, p.prod_id, v_depth + 1 from product p inner join tmp on p.parent_id = tmp.prod_id and tmp.depth = v_depth; set v_depth = v_depth + 1; truncate table tmp; insert into tmp select * from hier where depth = v_depth; else set v_done = 1; end if; end while; select p.prod_id, p.name as prod_name, b.prod_id as parent_prod_id, b.name as parent_prod_name, hier.depth from hier inner join product p on hier.prod_id = p.prod_id inner join product b on hier.parent_id = b.prod_id order by hier.depth, hier.prod_id; drop temporary table if exists hier; drop temporary table if exists tmp; end # delimiter ; call product_hier(3); call product_hier(5);