6

我写了一个存储的函数,它递归地调用自己。

但是,当我在查询中运行它时,我得到了这个无耻的错误:

错误:1424 SQLSTATE:HY000 (ER_SP_NO_RECURSION)

消息:不允许使用递归存储函数和触发器。

“不允许”?
正确的。我们为什么不直接禁用 WHILE 循环呢?

我可以以任何方式启用递归函数吗?
我发现了一个错误报告,但有什么解决方法吗?
我在 Windows XP(XAMPP 服务器)上运行 MySQL 5.1.41。

4

3 回答 3

4

MySQL 5.1 支持递归存储过程,但不支持递归函数。引用文档

存储函数不能递归。

存储过程中的递归是允许的,但默认情况下是禁用的。要启用递归,请将max_sp_recursion_depth服务器系统变量设置为大于零的值。存储过程递归增加了对线程堆栈空间的需求。如果增加 的值max_sp_recursion_depth,则可能需要通过增加thread_stack服务器启动时的值来增加线程堆栈大小。

于 2010-08-21T06:02:26.173 回答
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 |
+--------------+

谢尔盖·扎伊采夫。

于 2010-10-29T09:05:09.483 回答
3

可能不鼓励存储例程中的递归,因为 MySQL 需要限制其线程的堆栈大小。

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

在 32 位平台上,当运行 1,000 个线程时,地址空间压力很大,因此需要将堆栈设置得非常小,以避免地址空间耗尽。

堆栈溢出当然是非常糟糕的——它无法安全地恢复。所以我认为 MySQL 这样做是为了防止堆栈溢出,尤其是在 32 位平台上。

也就是说,现在任何使用 32 位操作系统来生产 MySQL 服务器的人都是疯了。

于 2010-08-21T07:34:47.363 回答