mysql Recursive limit 255 (as set by the max_sp_recursion_depth variable) was exceeded for

gema
Дата: 24.12.2012 06:51:24
Есть рекурсивная процедура. При её выполнении выходит ошибка "Код ошибки 1456, положение SQL HY000: Recursive limit 255 (as set by the max_sp_recursion_depth variable) was exceeded for routine".
Изначально выходила ошибка Thread stack overrun: 7840 bytes used of a 131072 byte stack, and 128000 bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack.Тогда я в настройках mysql прописала my.cnf: thread_stack=8M.
Как с этим бороться?
gema
Дата: 24.12.2012 06:53:48
В простых случаях, процедура выполнется.
tanglir
Дата: 24.12.2012 07:26:48
gema, любую рекурсивную функцию можно переписать в нерекурсивном виде.
gema
Дата: 24.12.2012 08:10:10
и чем её заменить?
tanglir
Дата: 24.12.2012 08:23:34
gema, нерекурсивной функцией //К.О.
Сэмулировать стек ручками, и дело в шляпе :)
gema
Дата: 24.12.2012 08:30:49
пример, ссылку в какую сторону рулить. Пожалуйста.
tanglir
Дата: 24.12.2012 08:36:51
gema, http://ru.wikibooks.org/wiki/Примеры_реализации_функции_факториал
Сравнить решения раздела 2 и раздела 1.

Если будут проблемы, давайте процедуру сюда, подумаем.
gema
Дата: 24.12.2012 09:34:24
Процедура такая:
DELIMITER $$

DROP PROCEDURE IF EXISTS `plo`.`curdemo`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `curdemo`(IN prod INT,IN k Decimal(20,10),OUT cost Decimal(20,10))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE rate_norm Decimal(20,10);
DECLARE summa Decimal(20,10);
DECLARE coeff Decimal(20,10);
DECLARE outlay INTEGER;
DECLARE type INTEGER;
DECLARE tmpcost Decimal(20,10);

DECLARE cur1 CURSOR FOR select norm,sum,coef,param,outlay_id from table where prod_id=prod;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

OPEN cur1;
set cost=0;
REPEAT
FETCH cur1 INTO  rate_norm,summa,coeff,type,outlay;
IF NOT done THEN

IF type=0 THEN SET cost=cost+summa ;
     ELSE call curdemo(outlay,k*coeff,tmpcost); SET cost=cost+coeff*tmpcost;
    END IF;
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
END$$

DELIMITER ;

Я так понимаю цикл у меня должен быть while. Ограничение цикла по coeff. Шаг цикла k*coef. А вот дальше непонятно, что делать...
tanglir
Дата: 24.12.2012 11:00:27
Смысл процедуры - есть дерево "родитель-потомок", причём родителями являются только записи с `type`=0.
Найти сумму поля "summa" по всем веткам дерева, начинающимся с заданного prod_id.
Так?

declare lcount unsigned;
declare curlevel unsigned;

create temporary table tmp_amts (level int, amt Decimal(20,10)); /*суммы по уровню*/
create temporary table tmp_levels (level int,id int); /*идшники по уровням*/

set curlevel:=0;

repeat
if curlevel=0 /*на 0 уровне попроще, тут "парентид" только один, заданный*/
 begin;
 insert into tmp_amts select curlevel,sum(summa)
  from table where prod_id=prod and type=0;
 insert into tmp_levels select 0,outlay_id
  from table where prod_id=prod and type<>0; 
 end;
else /*а глубже - берём идшники с предыдущего этапа*/
 begin;
 insert into tmp_amts select curlevel,sum(summa)
  from table join tmp_levels tl on table.id_prod=tl.id where type=0;
 insert into tmp_levels select curlevel,outlay_id
  from table join tmp_levels tl on table.id_prod=tl.id where type<>0 and tl.level=curlevel-1;
 end;
end if;
select count(*) into lcount from tmp_levels where level=curlevel; 
-- смотрим, есть ли что-то на следующем уровне
set curlevel=curlevel+1;
until lcount=0 or curlevel>=500; 
-- если потомков больше нет, то выходим
-- на всякий случай добавил ограничение на 500 уровней, ибо пишу "на глаз"

-- теперь в таблице tmp_amts получается список "уровень, сумма_по_уровню"
-- дальше с этим списком делайте что хотите
-- как прикрутить какие-то нелинейные/зависящие от уровня/суммы коэффициенты, думаю, догадаетесь уже сами
gema
Дата: 24.12.2012 13:06:38
спасибо, буду пробовать