我已经编写了一个存储的FUNCTION,它以递归方式调用自身。
然而,当我在查询中运行它时,我得到了这个无耻的错误:
错误:1424 SQLSTATE:HY000(ER_SP_NO_RECURSION)
消息:递归存储的函数和触发器不允许。
“不允许”?
对。为什么我们不只是禁用WHILE循环,而我们在它呢?
我可以以任何方式启用递归功能吗? 我找到了bug report,但是有没有解决办法? 我在Windows XP(XAMPP Server)上运行MySQL 5.1.41。
答案 0 :(得分:4)
MySQL 5.1支持递归存储过程,但不支持递归函数。引用docs:
存储的函数不能递归。
允许存储过程中的递归,但默认情况下禁用。要启用递归,请将
max_sp_recursion_depth
服务器系统变量设置为大于零的值。存储过程递归增加了对线程堆栈空间的需求。如果增加max_sp_recursion_depth
的值,可能需要通过在服务器启动时增加thread_stack
的值来增加线程堆栈大小。
答案 1 :(得分:3)
不鼓励在存储例程中递归,因为MySQL需要限制其线程的堆栈大小。
MySQL通常每个连接使用一个线程。 100或1000个连接是常见的。
在32位平台上,运行1,000个线程时会产生很大的地址空间压力,因此需要将堆栈设置得非常小,以避免地址空间耗尽。
堆栈溢出当然非常糟糕 - 无法安全地恢复。所以我认为MySQL这样做是为了防止堆栈溢出,尤其是在32位平台上。
也就是说,现在任何使用32位操作系统生产MySQL服务器的人都是疯了。
答案 2 :(得分:3)
没问题,Jenco。 不如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 |
+--------------+
Sergei Zaytsev。