ďťż

[SQL]Usuwanie drzewa wpisów

       

Podstrony


telcocafe

id | parent 1 | 0 2 | 1 3 | 1 4 | 2 5 | 2 6 | 0 7 | 6Tak się głowię i nie mogę niczego wymyślić. Chcę zrobić tak, by podczas usuwania wpisu z id=1 zostało usunięte całe drzewo, czyli wpisy od 1. do 5. Czy da się to zrobić poza rekurencją z poziomu PHP?



Przepraszam bardzo, ale gdzie tu zasada co do owego "drzewa" ?
Bo nie rozumiem, dlaczego dla ID=1 usuwane są niby wartości 0..2 ?

Weź no wytłumacz po polsku!

id to identyfikator elementu, a parent to identyfikator rodzica. Przykładowe drzewo (przedstawione przeze mnie):-1 |-2 | |-4 | |-5 |-3 -6 |-7I teraz jak najprościej usunąć całą gałąź z id=1?
Użytkownik andrzej_aa edytował ten post 16 marzec 2008, 22:24
musisz miec jakis kontener (chocby tablice) przechodujaca idy.
1 wpisujesz do niej id do usuniecia, i usuwasz ten element.
2. szukasz wszystkich elementow ktore jako parent maja id dowolnego element z tablicy, i usuwasz ten id ktorego szukasz z tej tablicy. dopisujesz idy wyszukanych elementow do tablicy, i usuwasz te elementy.
3. powtarzasz krok 2gi az tablica nie bedzie pusta.
Użytkownik Deadeye edytował ten post 23 marzec 2008, 02:00


Tak, tylko to jest rekurencja w PHP (o ile się nie mylę :-P), a mi chodzi o coś "taniego" w MySQL.

W MySQL też możesz stosować rekurencję :)
- Tworzysz funkcję MySQL
- Zapytaniem ją wywołujesz
- Ona wywołuje samą siebie dla wszystkich podrzędnych wpisów
- Usuwa aktualny wpis

No no, funkcje są fajne (dzięki! dotychczas myślałem, że są tylko w MsSQL :-P). Jednak jak na początki potrzebuję pomocy :-) Próbowałem na różne sposoby i nie wychodzi mi. To mój ostatni kod:CREATE FUNCTION PROPPARENTIDS (`_id` int) RETURNS int UNSIGNED BEGIN DELETE FROM `menu` WHERE `parent` IN (SELECT DROPPARENTIDS(`_id`)); RETURN (SELECT `id` FROM `menu` WHERE `parent`=`_id`); END;Funkcja powinna jednak zwracać tablicę (ale nie wiem jak to zrobić). Mimo tego przy wywołaniu SELECT DROPPARENTIDS(1) zwraca
Recursive stored functions and triggers are not allowed Co jest sprzeczne z założeniem. Mam wszystkie uprawnienia w bazie.

Szczerze mówiąc nie tego się spodziewałem, nie wiedziałem że funkcje nie mogą być rekursywne. Ale z tego co widzę procedury już mogą być.
Taki szybki test :)
CREATE PROCEDURE ext (id INT) BEGIN CALL ext(id+1); SELECT id; END; ... Query OK, 0 rows affected (0.02 sec) CALL ext(4); ERROR 1456 (HY000): Recursive LIMIT 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine ext
Co oznacza dwie rzeczy: procedury mogą być rekursywne; należy ustawić odpowiednią zmienną by na to pozwolić. A to że procedura nic bezpośrednio nie zwróci nie powinno być zbyt wielkim problemem.. można użyć TEMPORARY TABLE jeśli już koniecznie potrzebny nam wynik. Można też w ogóle się nie przejmować zwracaniem wyników i wewnątrz funkcji robić SELECT... i na wynikach tego zapytania uruchamiać samego siebie (by to powtórzyć + usunąć wpisy)

^^^^ kolorowanie składni - genialne ^^^^
Użytkownik Einzeinbleth edytował ten post 23 marzec 2008, 21:49

Tak, tylko to jest rekurencja w PHP (o ile się nie mylę :-P), a mi chodzi o coś "taniego" w MySQL.
jaka rekurencja o_O
zwykla petla while( tablica niepusta), i bezproblemowo ja mozna napisac jako procedure skladowana w sql ;]

No i mam takie zapytania:delimiter // CREATE PROCEDURE DROPPARENTIDS (IN `_id` int) BEGIN DECLARE `_tid` int; DECLARE `_ok` int DEFAULT 0; DECLARE `_cur` CURSOR FOR SELECT `id` FROM `menu` WHERE `parent`=`_id`; DECLARE CONTINUE HANDLER FOR NOT FOUND SET `_ok`=1; OPEN `_cur`; REPEAT FETCH `_cur` INTO `_tid`; CALL DROPPARENTIDS(`_tid`); UNTIL `_ok` END REPEAT; CLOSE `_cur`; DELETE FROM `menu` WHERE `parent`=`_id`; END; // delimiter ; SET GLOBAL max_sp_recursion_depth=1024; CALL DROPPARENTIDS(1);I występuje kolejny błąd, tym razem braku pamięci.
#1436 - Thread stack overrun: 103228 bytes used of a 196608 byte stack, and 96000 bytes needed. Use 'mysqle -O thread_stack=#' to specify a bigger stack. Poddaję się. Zrobię to w PHP - przynajmniej nie będę się tyle męczył.

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • nvm.keep.pl

  • Sitedesign by AltusUmbrae.