Na bazie artykulu:
http://www.sitepoint.com/article/hierarchi...data-database/3 o drzewkach SQLowych probuje stworzyc procedure skladowa do rpzebudowania drzewka.
Moja struktura tabeli Drzewko jest nastepujaca:
CREATE TABLE `Drzewko` (
`DrzewkoID` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`RodzicID` int(11) UNSIGNED DEFAULT NULL,
`LewaStrona` int(11) UNSIGNED DEFAULT NULL,
`PrawaStrona` int(11) UNSIGNED DEFAULT NULL,
`Nazwa` varchar(200) collate utf8_polish_ci NOT NULL DEFAULT '',
`PrzyjaznaNazwa` varchar(200) collate utf8_polish_ci NOT NULL DEFAULT '',
`Sciezka` text collate utf8_polish_ci NOT NULL,
PRIMARY KEY (`DrzewkoID`),
UNIQUE KEY `DrzewkoID` (`DrzewkoID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci;
Stworzylem soie taka procedure:
CREATE PROCEDURE `przebudujDrzewko`( IN varRodzicID INTEGER ( 11 ) , IN varLewaStrona INTEGER ( 11 ))
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
BEGIN DECLARE varDrzewkoID, varPrawaStrona INT;
DECLARE varKoniecWynikow TINYINT;
DECLARE kursor CURSOR
FOR SELECT DrzewkoID FROM Drzewko WHERE RodzicID = varRodzicID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET varKoniecWynikow = 1;
SET varPrawaStrona = varLewaStrona + 1;
SET varKoniecWynikow = 0;
OPEN kursor;
WHILE varKoniecWynikow <> 1 DO
FETCH kursor INTO varDrzewkoID; CALL przebudujDrzewko(varDrzewkoID, varPrawaStrona);
END WHILE;
CLOSE kursor;
UPDATE Drzewko
SET LewaStrona = varLewaStrona,
PrawaStrona = varPrawaStrona
WHERE DrzewkoID = varRodzicID;
END;
...ale... niechce zadzialac. Caly czas mam blad mowiacy o przekroczeniu max ilosci rekursywnych wywolan (mam to ustawione na 50). Drzewko ograniczylem nawet do 2 wpisow! i nadal to samo.
Nie mam pojecia co jest z tym nie tak.
Moze ktos ma pomysl?
----------------------------------------------------[ EDIT ]
OK. Czesciowo rozwiazalem problem. Otoz samo Open cursor nie powoduje, ze wywola sie zdarzenie NOT FOUND jezeli kursor nic nie zawiera. Trzeba dac FETCHa aby takie zdarzenie sie pojawilo i dopiero wewnatrz petli dac IFa, ktory wyjdzie nam z petli.... zamotane, wiem

)
Tak wyglada poprawiona procedura:
CREATE PROCEDURE `przebudujDrzewko`( IN varRodzicID INTEGER ( 11 ) , IN varLewaStrona INTEGER ( 11 ))
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
BEGIN DECLARE varDrzewkoID, varPrawaStrona INT;
DECLARE varKoniecWynikow BOOLEAN;
DECLARE kursor CURSOR
FOR SELECT DrzewkoID FROM Drzewko WHERE RodzicID = varRodzicID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET varKoniecWynikow = TRUE;
SET varPrawaStrona = varLewaStrona + 1;
OPEN kursor;
LOOP1: LOOP
FETCH kursor INTO varDrzewkoID; IF varKoniecWynikow = TRUE THEN
/*CLOSE kursor;*/
LEAVE LOOP1;
END IF;
CALL przebudujDrzewko(varDrzewkoID, varPrawaStrona);
END LOOP LOOP1;
CLOSE kursor;
UPDATE Drzewko
SET LewaStrona = varLewaStrona,
PrawaStrona = varPrawaStrona
WHERE DrzewkoID = varRodzicID;
END;
To jednak nie zmienia faktu, ze nie mozna zamknac kursora bo wszystkie wywolania rekurencyjne straca polaczenie z kursorem :|
----------------------------------------------------[ EDIT ]
Nie pytajcie sie jak to dziala, ale dziala

Oto kod, jezlei ktos by byl zainteresowany:
CREATE PROCEDURE `przebudujDrzewko`( IN varRodzicID INTEGER ( 11 ) , IN varLewaStrona INTEGER ( 11 ) , OUT varPrawaStrona INTEGER ( 11 ))
NOT DETERMINISTIC
SQL SECURITY DEFINER
COMMENT ''
BEGIN DECLARE varDrzewkoID INT;
DECLARE varKoniecWynikow BOOLEAN;
DECLARE kursor CURSOR
FOR SELECT DrzewkoID FROM Drzewko WHERE RodzicID = varRodzicID;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET varKoniecWynikow = TRUE;
SET varPrawaStrona = varLewaStrona + 1;
OPEN kursor;
LOOP1: LOOP
FETCH kursor INTO varDrzewkoID; IF varKoniecWynikow = TRUE THEN
LEAVE LOOP1;
END IF;
CALL przebudujDrzewko(varDrzewkoID, varPrawaStrona, varPrawaStrona);
END LOOP LOOP1;
CLOSE kursor;
UPDATE Drzewko
SET LewaStrona = varLewaStrona,
PrawaStrona = varPrawaStrona
WHERE DrzewkoID = varRodzicID;
SET varPrawaStrona = varPrawaStrona + 1;
END;
Ten post edytował Seth 18.10.2006, 13:53:54