MySQL не поддерживает рекурсивные функции? Зачем? с тех пор как?

Я написал сохраненную ФУНКЦИЮ, которая вызывает себя рекурсивно.

Однако когда я запускаю его в запросе, я получаю эту бессовестную ошибку:

Ошибка: 1424 SQLSTATE: HY000 (ER_SP_NO_RECURSION)

Сообщение: Рекурсивные сохраненные функции и триггеры запрещены.

Не разрешено?
Верно. Почему бы нам просто не отключить циклы WHILE, пока мы на них?

Могу ли я каким-либо образом включить рекурсивные функции?
Я нашел отчет об ошибке, но есть ли обходные пути?
Я использую MySQL 5.1.41 в Windows XP (сервер XAMPP).


person Robin Rodricks    schedule 21.08.2010    source источник
comment
База данных предназначена для получения данных, а не для программирования. Есть ли причина, по которой вы пытаетесь реализовать сложную, трудную для прогнозирования или оптимизации логику в хранимой процедуре, а не в своем приложении?   -  person Borealid    schedule 21.08.2010
comment
stackoverflow.com/questions/3438111 /   -  person Novemberland    schedule 21.08.2010
comment
Бесстыдная ошибка! Есть способ включить рекурсивные функции; вам нужно изменить код MySQL, чтобы они работали.   -  person Brian Hooper    schedule 21.08.2010
comment
Какой код MySQL? Не просите меня создать собственную сборку MySQL Server.   -  person Robin Rodricks    schedule 21.08.2010


Ответы (3)


Нет проблем, Дженко. Не так эффективно, как функции PostgreSQL, но это возможно и в процедурах MySQL:

DELIMITER $$
DROP PROCEDURE IF EXISTS test.factorial_proc$$
CREATE PROCEDURE test.factorial_proc
(
   IN n   BIGINT, 
  OUT res BIGINT 
) 
BEGIN
  SET max_sp_recursion_depth=10; 
  IF n >= 2 THEN
    CALL test.factorial_proc (n-1, res);
    SELECT n * res INTO res;
  ELSE
    SELECT n INTO res;
  END IF;
END$$
DELIMITER ;

[test]> CALL test.factorial_proc (5, @res);
[test]> CALL test.factorial_proc (5, @res1);
[test]> select @res * @res1;
+--------------+
| @res * @res1 |
+--------------+
|        14400 |
+--------------+

Сергей Зайцев.

person Sergei Zaytsev    schedule 29.10.2010

MySQL 5.1 поддерживает рекурсивные хранимые процедуры, но не рекурсивные функции. Цитата из документов:

Сохраненные функции не могут быть рекурсивными.

Рекурсия в хранимых процедурах разрешена, но по умолчанию отключена. Чтобы включить рекурсию, установите _1 _ системной переменной сервера значение больше нуля. Рекурсия хранимой процедуры увеличивает потребность в пространстве стека потоков. Если вы увеличите значение _2 _, может потребоваться увеличить размер стека потоков, увеличив значение _ 3_ при запуске сервера.

person Daniel Vassallo    schedule 21.08.2010
comment
Я все еще хотел бы решение с использованием FUNCTIONS, потому что у меня есть рекурсивный метод, который вызывает себя, ожидая возвращаемых значений. Если бы я использовал ПРОЦЕДУРУ, я бы не смог это сделать ... не так ли? - person Robin Rodricks; 21.08.2010
comment
@Jenko: Все, что можно сделать с помощью рекурсии, можно переписать с помощью итерации: stackoverflow.com/questions/931762/ - person Daniel Vassallo; 21.08.2010

Вероятно, рекурсия в хранимых подпрограммах не приветствуется, потому что MySQL должен ограничивать размер стека своих потоков.

MySQL обычно использует один поток на каждое соединение. Обычны 100 или 1000 подключений.

На 32-битных платформах при выполнении 1000 потоков возникает значительная нехватка адресного пространства, поэтому стеки должны быть очень маленькими, чтобы избежать исчерпания адресного пространства.

Переполнение стека, конечно, очень плохо - его нельзя безопасно восстановить. Поэтому я думаю, что MySQL делает это для предотвращения переполнения стека, особенно на 32-битных платформах.

Тем не менее, любой, кто использует 32-битную ОС для производственного сервера MySQL в настоящее время, безумен.

person MarkR    schedule 21.08.2010
comment
Переполнение стека, конечно, очень плохо - его нельзя безопасно восстановить, это в корне неверно. ВСЕ разумные языки программирования более высокого уровня могут безопасно восстанавливаться после переполнения стека, такие как Java, Perl, Python, ... - person intgr; 07.01.2011