MySQL中的递归存储函数

tir*_*hen 8 mysql sql recursion recursive-query stored-functions

我正在尝试创建一个递归构建特定类别路径的函数

CREATE FUNCTION getPath(inId INT)
RETURNS TEXT
DETERMINISTIC
BEGIN
    DECLARE return_path TEXT;
    DECLARE return_parent_id INT;
    SELECT CONCAT('/', name) INTO return_path FROM article_categories WHERE id = inId;
    SELECT parent_id INTO return_parent_id FROM article_categories WHERE id = inId;

    IF return_parent_id > 0 THEN
        SELECT CONCAT(getPath(return_parent_id), return_path) INTO return_path;
    END IF;

    RETURN return_path;
END
Run Code Online (Sandbox Code Playgroud)

当我尝试使用没有父项的类别(parent_id = 0)运行此函数时,它工作正常,但是当我尝试一个parent_id> 0的类别时,我得到1424递归存储函数和触发器是不允许的.

我该如何解决这个问题?我将在常规的Web托管服务上托管此代码,该服务至少应该具有MySQL服务器版本5.1.


在Ike Walker的帮助下,我做了一个很好的工作

DROP PROCEDURE IF EXISTS getPath;
DELIMITER //
CREATE PROCEDURE getPath(IN category_id INT UNSIGNED, OUT return_path TEXT)
BEGIN
    DECLARE parent_id INT UNSIGNED;
    DECLARE path_result TEXT;

    SET max_sp_recursion_depth=50;

    SELECT CONCAT('/', ac.name), ac.parent_id INTO return_path, parent_id FROM article_categories AS ac WHERE ac.id = category_id;

    IF parent_id > 0 THEN
        CALL getPath(parent_id, path_result);
        SELECT CONCAT(path_result, return_path) INTO return_path;
    END IF;
END //
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

然后我用这样的东西来称呼它

CALL getPath(72, @temp); SELECT @temp;
Run Code Online (Sandbox Code Playgroud)

Ike*_*ker 10

即使你设置了max_sp_recursion_depth,MySQL也不允许递归FUNCTION.

如果设置max_sp_recursion_depth,它在PROCEDURE中最多允许255次递归.

因此,我建议您使用过程替换函数,使用INOUT变量作为return_path.


Fan*_*nto 5

从您问题中的存储过程中,*在@Ike Walker的帮助下,

DROP PROCEDURE IF EXISTS getPath;
DELIMITER $$
CREATE PROCEDURE getPath(IN category_id INT UNSIGNED, OUT return_path TEXT)
BEGIN
    DECLARE parent_id INT UNSIGNED;
    DECLARE path_result TEXT;
    SET max_sp_recursion_depth=50;

    SELECT CONCAT('/', ac.name), ac.parent_id INTO return_path, parent_id FROM article_categories AS ac WHERE ac.id = category_id;
    IF parent_id > 0 THEN
        CALL getPath(parent_id, path_result);
        SELECT CONCAT(path_result, return_path) INTO return_path;
    END IF;
END $$
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)

创建一个函数:

DROP FUNCTION IF EXISTS getPath;
CREATE FUNCTION getPath(category_id INT) RETURNS TEXT DETERMINISTIC
BEGIN
    DECLARE res TEXT;
    CALL getPath(category_id, res);
    RETURN res;
END$$
Run Code Online (Sandbox Code Playgroud)

接下来,您可以选择:

SELECT category_id, name, getPath(category_id) AS path FROM article_categories ;
Run Code Online (Sandbox Code Playgroud)