MySQL不支持递归函数?为什么?从什么时候开始?

发布于 2024-09-14 23:59:32 字数 384 浏览 7 评论 0原文

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

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

错误:1424 SQLSTATE:HY000 (ER_SP_NO_RECURSION)

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

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

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

I've written a stored FUNCTION that calls itself, recursively.

However when I run it in a query I get this shameless error:

Error: 1424 SQLSTATE: HY000 (ER_SP_NO_RECURSION)

Message: Recursive stored functions and triggers are not allowed.

"Not allowed"?
Right. Why don't we just disable WHILE loops also, while we're at it?

Can I enable recursive functions in any way?
I found a bug report, but are there any workarounds?
I'm running MySQL 5.1.41 on Windows XP (XAMPP Server).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

っ左 2024-09-21 23:59:32

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

存储的函数不能递归。

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

MySQL 5.1 supports recursive stored procedures, but not recursive functions. Quoting the 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.

猛虎独行 2024-09-21 23:59:32

没问题,詹科。
不如 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。

No problem, Jenco.
Not so efficient as PostgreSQL functions, but it's possible in MySQL procedures also:

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.

梦与时光遇 2024-09-21 23:59:32

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

MySQL 通常每个连接使用一个线程。数百或数千个连接很常见。

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

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

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

Probably recursion in stored routines is discouraged because MySQL needs to limit its threads' stack size.

MySQL typically uses one thread per connection. 100s or 1000s of connections are common.

On 32-bit platforms, there is significant address-space pressure when running 1,000 threads, so the stacks need to be set very small to avoid address-space exhaustion.

Stack overflow is, of course, very bad - it can't be recovered from safely. So I think MySQL does this to prevent stack overflows, especially on 32-bit platforms.

That said, anyone using a 32-bit OS for a production MySQL server nowadays is insane.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文