2010-09-20 6 views
5

Je suis en train de faire une fonction qui construit récursivement un chemin pour une catégorie spécifiquerécursives fonctions stockées dans 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 

Lorsque je tente d'exécuter cette fonction avec une catégorie qui n'a pas de parents (id_parent = 0) ça marche bien mais quand j'essaie une catégorie qui a un parent_id> 0, je reçois 1424 fonctions récursives et les triggers ne sont pas autorisés.

Comment puis-je contourner ce problème? Je vais héberger ce code sur un service d'hébergement web régulier qui devrait avoir au moins la version 5.1 du serveur MySQL.


Après l'aide de Ike Walker J'ai fait une precedure place qui fonctionne 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 ; 

J'utilise alors quelque chose comme ça pour l'appeler

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

En ce moment je développe sur Ubuntu avec la version MySQL-Server: 5.1.41-3ubuntu12.6 (Ubuntu) – Tirithen

+0

J'ai trouvé http: // forums .mysql.com/read.php? 98,224107,224638 # msg-224638 qui parle de SET max_sp_recursion_depth = N; où N est le nombre de récursions à autoriser. Mais je reçois toujours 1424 fonctions stockées récursives et les déclencheurs ne sont pas autorisés. – Tirithen

Répondre

7

MySQL ne permet pas récursive FUNCTION, même si vous définissez max_sp_recursion_depth.

Il autorise jusqu'à 255 récursions dans une procédure si vous définissez max_sp_recursion_depth.

Je vous recommande donc de remplacer votre fonction par une procédure, en utilisant une variable INOUT pour le chemin de retour.

+0

Merci d'avoir trié cela, j'ai maintenant fait une procédure à la place: – Tirithen

+0

PROCÉDURE DE CHUTE SI EXISTE getPath; DELIMITER // CREATE PROCEDURE getPath (IN catégorie_id INT UNSIGNED, OUT return_path TEXT) BEGIN \t DÉCLARER parent_id INT UNSIGNED; \t DECLARE path_result TEXT; \t SET max_sp_recursion_depth = 50; \t SELECT CONCAT ('/', ac.name) DANS le chemin de retour FROM article_categories AS ac WHERE ac.id = category_id; \t SELECT ac.parent_id INTO parent_id FROM article_categories AS ac Où ac.id = category_id; \t SI parent_id> 0 PUIS \t \t CALL getPath (parent_id, path_result); \t \t SELECT CONCAT (path_result, chemin_retour) INTO chemin_retour; \t END IF; END // DELIMITER; – Tirithen

1

De la procédure stockée dans votre question, * avec l'aide 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 ; 

Créer une fonction:

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

Ensuite, vous pouvez sélectionner:

SELECT category_id, name, getPath(category_id) AS path FROM article_categories ; 
Questions connexes