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

Вниз

Обновление поля PATH в иерархической таблице   Найти похожие ветки 

 
Vadim   (2002-02-11 12:03) [0]

Дано:
1. таблица CATALOG1, поля ID,PARENT,CAPTION,PATH.
2. PARENT ссылается на ID этой же таблицы.
3. в PATH хранится путь вида CAPTION_LEVEL0//...CAPTION_LEVELN//

Задача: при смене CAPTION любого PARENT обеспечить обновление PATH во всех дочерних узлах, включая вложенные.

Варианты решения:
1. При помощи триггеров - в Oracle невозможен (mutating).
2. При помощи ХП - не рассматривается.
3. Средствами SQL. Вот заготовка:
update CATALOG1 p
set p.PATH=(select p1.PATH||p.CAPTION||"//"
from CATALOG1 p1
where p1.ID=p.PARENT)
where p.ID in (select ID from CATALOG1
start WITH PARENT=12345
connect by PRIOR ID=PARENT;

Ясно, что она работать не будет, поскольку порядок строк в операторе UPDATE не всегда совпадает с требуемым (PARENT -> CHILD).

Вопрос: Есть ли красивый способ решения задачи?


 
fnatali   (2002-02-11 12:38) [1]

Решала похожую задачу, но с точностью до наоборот. :)
Если тебе поможет, могу описать. Пришлось строить рекурсивную функцию для получения полного caption в твоём случае. А потом уже что-то с ним делать. Но описывать довольно объёмно. Если интересует, дай знать.


 
fnatali   (2002-02-11 13:04) [2]

Ну вот так попробовала сделать:
Функция:
FUNCTION XXPI2 ( caption IN varchar2,
P_par_id in number,
p_id IN number)

RETURN varchar2 IS
x_cap varchar2,
X_par_id number,
x_id number,
x_s varchar2(255);

BEGIN
X_par_id:=p_par_id;
x_id := p_id;
x_s := caption;

LOOP

select caption,id,parent_id into x_cap,x_id,x_par_id
from catalog1
where id=x_par_id;

x_s:=x_cap||"//"||x_s;

END LOOP;
return x_s;

EXCEPTION when NO_DATA_FOUND then
return x_s;

END; -- Function XXPI

Возвращает полный caption для заданных id и parent_id.
Затем нужно вызвать её в SQL например так:
update catalog1 p
set p.path=XXPI2(:caption,:parent,:id)
Писала навскидку, так что могут быть ошибочки :)


 
Vadim   (2002-02-11 17:02) [3]

fnatali © Спасибо за ответ
Да, действительно, имея такую функцию, можно сделать так:
update CATALOG1 set PATH=func(ID)
where p.ID in (select ID from CATALOG1
start WITH PARENT=12345
connect by PRIOR ID=PARENT;


правда, при этом func() придётся для каждой строки просчитывать PATH от самого верхнего узла, что несколько снизит производительность.


 
fnatali   (2002-02-12 07:19) [4]

>просчитывать PATH от самого верхнего узла
>в PATH хранится путь вида CAPTION_LEVEL0//...CAPTION_LEVELN//
Но если не просчитывать его с самого верхнего уровня, то тогда придётся делать разбор PATH и, если, например, изменился уровень N-1, делать изменения в строке PATH? Или я чего-то не понимаю? У тебя ведь написано ОБНОВЛЕНИЕ PATH, т.е. я так поняла, что измениться в этой строке может любой уровень?





 
Vadim   (2002-02-12 10:34) [5]

Зачем делать разбор PATH? Изменённый узел известен,
можно просто взять PATH предыдущего уровня и добавить CAPTION, затем та же операция для всех его потомков и так последовательно по иерархии от изменённого узла до всех потомков.
Это был бы самый эффективный путь, только вот как это грамотно организовать?


 
fnatali   (2002-02-13 05:58) [6]

Тогда, чтобы формировать x_s только до нужного узла, можно ввести ещё один входной параметр - id узла, из которого нужно взять PATH. И сделать проверку
if x_id=id then
x_s=x_path||x_s
и выйти из цикла.


 
Vadim   (2002-02-13 08:57) [7]

Идея ясна.
Однако я пока всё - таки реализовал решение несколько иначе:

procedure SetPath(ParentID in number, ParentPath in VARCHAR) is
cursor p is select ID,Path from CATALOG_PLACES
where PARENT=SetPath.ParentID;
r p%ROWTYPE;
Begin
Update CATALOG_PLACES
set PATH=SetPath.ParentPath||CAPTION||"//"
Where PARENT=SetPath.ParentID;
Commit;
Open p;
Loop
Fetch p into r;
Exit When p%NOTFOUND;
SetPath(r.ID, r.PATH);
End Loop;
Close p;
End;


Спасибо за участие!



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

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

Наверх





Память: 0.46 MB
Время: 0.004 c
14-32569
ev
2002-01-26 14:11
2002.03.11
Операционная система


1-32453
Grim Rider
2002-02-22 08:34
2002.03.11
Как прицепить ActiveX Dll?


14-32563
Егор
2002-01-18 08:51
2002.03.11
Microsoft Agent


14-32560
Вадим
2002-01-27 17:44
2002.03.11
Fine Reader 5 & WinXP


1-32443
Turalyon
2002-02-20 09:00
2002.03.11
Сервис





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский