Форум: "Базы";
Текущий архив: 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