Domanda

Sto cercando di fare una funzione che costruisce in modo ricorsivo un percorso per una specifica categoria

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

Quando si tenta di eseguire questa funzione con una categoria che non ha genitori (parent_id = 0) che funziona benissimo ma quando provo una categoria che ha un parent_id> 0 vengo 1424 funzioni e trigger ricorsiva memorizzati non sono ammessi.

Come faccio a risolvere questo? Ho intenzione di ospitare questo codice su un regolare servizio di web hosting che dovrebbe avere almeno MySQL server versione 5.1.


Dopo qualche aiuto da Ike Walker ho fatto un precedure, invece, che funziona bene

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 ;

Ho quindi utilizzare qualcosa di simile a chiamarlo

CALL getPath(72, @temp); SELECT @temp;
È stato utile?

Soluzione

MySQL non consente funzioni ricorsive, anche se si imposta max_sp_recursion_depth.

Non permette fino a 255 ricorsione in una procedura se si imposta max_sp_recursion_depth.

Quindi vi consiglio di sostituire la funzione con una procedura, utilizzando una variabile INOUT per la return_path.

Altri suggerimenti

Dal stored procedure nella sua interrogazione, * con l'aiuto di @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 ;

Creare una funzione:

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

In seguito, è possibile selezionare:

SELECT category_id, name, getPath(category_id) AS path FROM article_categories ;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top