2010-09-20 175 views
5

que estoy tratando de hacer una función recursiva que construye un camino para una categoría específicafunciones recursivas almacenados en MySQL

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 

Cuando trato de ejecutar esta función con una categoría que no tiene padres (parent_id = 0) funciona bien, pero cuando pruebo una categoría que tiene un parent_id> 0 obtengo 1424 funciones almacenadas recursivas y los desencadenadores no están permitidos.

¿Cómo puedo solucionar esto? Voy a alojar este código en un servicio de alojamiento web normal que debe tener al menos la versión 5.1 del servidor MySQL.


Después de una cierta ayuda de Ike Walker he hecho un procedimineto en cambio, que funciona bien

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 ; 

Luego utilizo algo como esto llamarlo

CALL getPath(72, @temp); SELECT @temp; 
+0

En este momento estoy desarrollando en Ubuntu con la versión del servidor MySQL: 5.1.41-3ubuntu12.6 (Ubuntu) – Tirithen

+0

He encontrado http: // foros .mysql.com/read.php? 98,224107,224638 # msg-224638 que habla de SET max_sp_recursion_depth = N; donde N es el número de recurrencias para permitir. Pero sigo recibiendo 1424 funciones almacenadas recursivas y los disparadores no están permitidos. – Tirithen

Respuesta

7

MySQL no permite recursiva FUNCIONES, incluso si establece max_sp_recursion_depth.

Permite hasta 255 recursiones en un PROCEDIMIENTO si establece max_sp_recursion_depth.

Así que le recomiendo que reemplace su función con un procedimiento, usando una variable INOUT para return_path.

+0

Gracias por resolver esto, en su lugar, realicé un procedimiento: – Tirithen

+0

PROCEDIMIENTO DE CAÍDA SI EXISTE getPath; DELIMITER // CREAR PROCEDIMIENTO getPath (IN category_id INT UNSIGNED, OUT return_path TEXT) BEGIN \t DECLARAR parent_id INT UNSIGNED; \t DECLARAR path_result TEXT; \t SET max_sp_recursion_depth = 50; \t SELECCIONE CONCAT ('/', ac.name) EN return_path FROM article_categories AS ac WHERE ac.id = category_id; \t SELECCIONAR ac.parent_id EN parent_id FROM article_categories AS ac WHERE ac.id = category_id; \t SI parent_id> 0 THEN \t \t LLAME getPath (parent_id, path_result); \t \t SELECCIONAR CONCAT (path_result, return_path) INTO return_path; \t END IF; END // DELIMITER; – Tirithen

1

A partir del procedimiento almacenado en su pregunta, * con la ayuda de @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 ; 

Crear una función:

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

A continuación, puede seleccionar:

SELECT category_id, name, getPath(category_id) AS path FROM article_categories ; 
Cuestiones relacionadas