6

我写了一个存储函数,它递归地调用自己。MySQL不支持递归函数?为什么?从何时起?

然而,当我在查询运行它,我得到这个无耻的错误:

Error: 1424 SQLSTATE: HY000 (ER_SP_NO_RECURSION)

Message: Recursive stored functions and triggers are not allowed.

“不允许”?
没错。为什么我们不只是禁用WHILE循环,而我们还在?

我可以以任何方式启用递归函数吗?
我找到bug report,但是有没有解决方法?
我在Windows XP(XAMPP服务器)上运行MySQL 5.1.41。

+2

数据库用于检索数据,而不是用于编程。您是否有理由试图在存储过程中而不是在应用程序中执行复杂的,难以预测或优化的逻辑? – Borealid 2010-08-21 06:00:03

+0

http://stackoverflow.com/questions/3438111/mysql-stored-procedure-that-c​​alles-itself-recursively – Novemberland 2010-08-21 06:05:22

+1

无耻的错误!有一种方法可以启用递归函数;你必须修改MySQL代码才能使它们工作。 – 2010-08-21 06:36:43

回答

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 | 
+--------------+ 

谢尔盖Zaytsev。

4

MySQL 5.1支持递归存储过程,但不支持递归函数。引述docs

Stored functions cannot be recursive.

Recursion in stored procedures is permitted but disabled by default. To enable recursion, set the max_sp_recursion_depth server system variable to a value greater than zero. Stored procedure recursion increases the demand on thread stack space. If you increase the value of max_sp_recursion_depth , it may be necessary to increase thread stack size by increasing the value of thread_stack at server startup.

+0

我仍然喜欢使用函数的解决方案,因为我有一个递归方法,它调用自己期待返回值。如果我使用了PROCEDURE,那么我就无法做到这一点......我愿意吗? – 2010-08-21 08:04:45

+1

@Jenko:任何可以使用递归完成的事情都可以使用迭代来重写:http://stackoverflow.com/questions/931762/can-every-recursion-be-converted-into-iteration – 2010-08-21 08:09:59

3

中保存的程序可能递归气馁,因为MySQL需要限制其线程的堆栈大小。

MySQL通常每个连接使用一个线程。 100秒或1000秒的连接是常见的。

在32位平台上,运行1000个线程时会产生巨大的地址空间压力,因此需要将堆栈设置得非常小以避免地址空间耗尽。

堆栈溢出当然非常糟糕 - 无法从安全中恢复。所以我认为MySQL这样做是为了防止堆栈溢出,特别是在32位平台上。现在任何使用32位操作系统生产MySQL服务器的人都是疯了。

+0

“堆栈溢出当然,非常糟糕 - 它无法从安全中恢复“这是完全错误的。所有合理的高级编程语言都能够安全地从堆栈溢出中恢复,比如Java,Perl,Python ...... – intgr 2011-01-07 08:38:21