Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2007.07.15;
Скачать: [xml.tar.bz2];

Вниз

Рекурсия, дерево   Найти похожие ветки 

 
azamatufa ©   (2007-04-11 20:18) [0]

Приветствую, уважаемые!

Не смог найти, получить ответа на мой вопрос, решил новую тему создать.

Есть у меня классическое дерево "Подразделения в организации":

ID   Name            ParentID
1    Отдел1              0
2    Отдел2              0
3    под_Отдел1        1
4    под_Отдел2        2
5    под_под_Отдел1  3  

Задача: нужна рекурсия для удаления определенной вершины и всех ее детей и внуков...

да, база данных Jet (Access), поэтому рекурсия при помощи SQL не пойдет...

Спасибо!!!


 
Johnmen ©   (2007-04-11 20:27) [1]


>  поэтому рекурсия при помощи SQL не пойдет...

А при помощи чего пойдёт?


 
azamatufa ©   (2007-04-11 20:41) [2]

Имел ввиду что в MS SQL есть возможность написания рекурсий языком SQL (процедуры, функции, переменные..)

у меня же на вооружении декстоп SQL (без процедур и функций).

использую ADOTable, ADOQuery.. ну и соответственно рекурсия на Delphi.


 
Johnmen ©   (2007-04-11 20:44) [3]


> ну и соответственно рекурсия на Delphi.

А в чём конкретно проблема с рекурсией?


 
azamatufa ©   (2007-04-12 06:23) [4]

Вот моя попытка собрать все значения ID подлежащих удалению.
Q - ADOQuery - запрос


// -----------------------------------------------------------
procedure TFormTree.Make_Del_List(ID:integer);
begin
 if HasChild(ID) then begin
   while not Q.Eof do begin
     Make_Del_List(Q.FieldByName("ID").AsInteger);
   end;
 end;
 List.Add(IntToStr(ID));     // в Лист добавили ID
end;

// ---------- есть ли дети -----------------------
function TFormTree.HasChild(ID:integer):boolean;
begin
 Q.Close;
 Q.SQL.Clear;
 Q.SQL.Add("SELECT * FROM Dep WHERE ParentID = " + IntToStr(ID));
 Q.Open;
 Result := Q.RecordCount > 0;
end;


Это работает не так как надо бы.
А именно, так:
если есть 3 ребенка - то их находит.
если есть 3 ребенка и 1 внук, то находит ребенка, внука, но не находит еще 2 детей...

Короче, дайте рабочий код!! Кто это делал??? или кто может...

Заранее благодарю!


 
ЮЮ ©   (2007-04-12 08:50) [5]

Q должна быть локальным обектом Make_Del_List, а не глобальным объектом, как в твоем случае


 
Johnmen ©   (2007-04-12 09:08) [6]

Кто использует RecordCount для проверки наличия записей в НД, тот сам себе злобный буратино.
Кто использует IsEmpty, тот правильный пацан.

> Короче, дайте рабочий код!!

Помечтай...:)


 
Сергей М. ©   (2007-04-12 09:42) [7]


> Вот моя попытка собрать все значения ID подлежащих удалению


Зачем их собирать ?
Если поддерживается механизм каскадных операций и/или триггерный механизм, то достаточно знать ID удаляемого узла, все остальное сделают эти механизмы.


 
Johnmen ©   (2007-04-12 09:51) [8]


> Сергей М. ©   (12.04.07 09:42) [7]
> Если поддерживается механизм каскадных операций ..., то достаточно знать ID удаляемого
> узла, все остальное сделают эти механизмы.

А вот и нет :)
Самокаскад No Pasaran!


 
Сергей М. ©   (2007-04-12 09:59) [9]


> Johnmen ©   (12.04.07 09:51) [8]


Чтой-то вдруг ?)

Ну разумеется, механизмы эти в БД д.б. задействованы и настроены должным образом, прежде чем уповать на них).. Я же не утверждаю, что вся эта петрушка  заработает сама по себе волшебным образом .. Просто ручки приложить надо)

p.s.
А ноги у вопроса растут из другой ветки, где Автор жаловался, что он, мол, якобы не может задействовать каскадные операции из-за ParentId=Null у корневых узлов.


 
Jan1   (2007-04-12 10:34) [10]

только-что проверил - каскадные внешние ключи нормально работают в Access, чего нельзя сказать о MS SQL :(


 
Сергей М. ©   (2007-04-12 10:36) [11]


> Jan1   (12.04.07 10:34) [10]


> чего нельзя сказать о MS SQL


Зато там есть триггерный механизм)


 
Johnmen ©   (2007-04-12 10:41) [12]


> Сергей М. ©   (12.04.07 09:59) [9]
>Чтой-то вдруг ?)

Не вдруг. А чтой-то - так сделано...
И не только в MSSQL.


 
Сергей М. ©   (2007-04-12 10:50) [13]


> Johnmen ©   (12.04.07 10:41) [12]


> так сделано


Не понял .. Что сделано-то ?
Поясни ..


 
Johnmen ©   (2007-04-12 10:55) [14]


> Сергей М. ©   (12.04.07 10:50) [13]
> Что сделано-то ?

Если поддерживается механизм каскадных операций, то это не значит, что поддерживается самокаскад. Вот это неподдержание и сделано...


 
Сергей М. ©   (2007-04-12 11:17) [15]


> Johnmen ©   (12.04.07 10:55) [14]


Ах вот ты  о чем)


 
azamatufa ©   (2007-04-12 15:07) [16]


> Q должна быть локальным обектом Make_Del_List, а не глобальным
> объектом, как в твоем случае


Вот спасибо, умный человек! Действительно. Вот оно решение:

// ----------------------------------------------------
procedure TFormTree.Make_Del_List(ID:integer);
var
 Q: TADOQuery;         // !! Локально !!!
begin
 Q := TADOQuery.Create(nil);
 Q.ConnectionString := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb;Persist Security Info=False";
 Q.SQL.Add("SELECT * FROM Dep WHERE ParentID = " + IntToStr(ID));
 Q.Open;
 if not Q.IsEmpty then begin
   while not Q.Eof do begin
     Make_Del_List(Q.FieldByName("ID").AsInteger);
     Q.Next;
   end;
 end;
 List.Add(IntToStr(ID));
 Q.Free;
end;



Спасибо Johnmen"у, теперь я не злой буротино, а реальный патцан.. ибо юзаю Q.IsEmpty !

=)

Отличный у Вас форум! простой и понятный, не то что дельфикингдом.. 1. работает через одно место 2. надо быть шизо маленько чтобы понимать их аббревиатуры.. свитки.. папирусы... бе.


 
ANB ©   (2007-04-14 09:24) [17]


> azamatufa ©   (12.04.07 15:07) [16]

Форум у нас действительно клевый.
Но хотелось бы предостеречь от некоторых граблей.
1. Рекурсия хорошо кушает стек и при большом уровне вложенностей можешь вполне хапнуть его переполнение. Посему линейный алгоритм как то побезопаснее будет, хотя и сложнее. У меня где то валялся исходник работы с деревьями на Clipper без рекурсии (я уже ловил переполнение стека и реализовал линейный алгоритм) - можно адаптировать его к делфи.
2. Зачем зашиваться на аксессе ? Это создание себе трудностей с мужественным их затем преодолением. Скачай Оракл XE - он официально халявый (даже для коммерческих целей), ограничения смешные, много вкусностей в хранимой логике и есть специальные средства для работы с парентовыми деревьями.


 
ЮЮ ©   (2007-04-14 09:39) [18]


> ибо юзаю Q.IsEmpty !

конкретном случае он лишний. Цикл
while not Q.Eof do begin
 ...
end;
отработает правильно и без этой проверки


 
azamatufa ©   (2007-04-14 22:14) [19]


> Зачем зашиваться на аксессе ? Это создание себе трудностей
> с мужественным их затем преодолением. Скачай Оракл XE -
> он официально халявый (даже для коммерческих целей), ограничения
> смешные, много вкусностей в хранимой логике и есть специальные
> средства для работы с парентовыми деревьями.

заманчиво, конечно... спасибо за совет. Я недавно пробовал FireBird, использовал родную палитру InterBase, вроде ниче..
чем Аксесс плох, если не ошибаюсь, так это работа когда много юзеров дербанят одну базу.. т.е. там нет таких вещей как rollback, commit.... (в моем случае аксесс подходит - один юзер одна база..).
а так, дай бог, планирую перейти на что-нибудь бесплатное (FireBird, MySQL либо как Вы подсказали Оракл ХЕ...)


> конкретном случае он лишний. Циклwhile not Q.Eof do begin
>  ...end;отработает правильно и без этой проверки

Вы совершенно правы!



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2007.07.15;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.043 c
1-1178985928
mr1Andersen
2007-05-12 20:05
2007.07.15
Здравствуйте Мастера. Каким образом Delphi кодирует(запоминает) в


15-1181906747
Predfer
2007-06-15 15:25
2007.07.15
Компьютер не работает!


15-1181737948
ferr
2007-06-13 16:32
2007.07.15
А вдруг кто не видел =)


15-1181633805
IMHO
2007-06-12 11:36
2007.07.15
С Днем России, россияне!


15-1182185234
Грициан
2007-06-18 20:47
2007.07.15
Доведем bbc до истерики





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский