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