MySQL не поддерживает рекурсивные функции?Зачем?с каких пор? - PullRequest
6 голосов
/ 21 августа 2010

Я написал сохраненную функцию, которая вызывает себя рекурсивно.

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

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

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

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

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

Ответы [ 3 ]

4 голосов
/ 21 августа 2010

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

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

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

3 голосов
/ 29 октября 2010

Нет проблем, Дженко. Не так эффективно, как функции 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 |
+--------------+

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

3 голосов
/ 21 августа 2010

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

MySQL обычно использует один поток на соединение. 100 или 1000 соединений являются общими.

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

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

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

...