|
|
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
Есть довольно стандартная таблица, реализующая хранение иерархической структуры: ID,ParentID,Summa,Folder. Поле Folder должно хранить 1 -если данный элемент имеет деток, 0 - соответственно устанавливаем для конечных элементов. Никак не могу придумать триггер, поддерживающий данное правило, при условии что дерево обновляется не построчно, а пакетной операцией. Может кто подскажет как решить данную проблему? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2002, 09:57:56 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
Убери поле Folder и проблема снимется сама собой. Оно избыточно, так как всегда можно узнать в запросе, есть ли детки или нет у конкретной ноды. При желании можно написать вьюху, в которой это поле будет вычисленным ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2002, 10:45:33 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
как-то так например можно update t set Folder = 0 from tbl t, inserted i where t.ID=i.ID update p set Folder = 1 from tbl t, tbl p, inserted i where t.ID=p.ParentID and p.ID=i.ID ну и еще есть масса вариантов. Можно сделать без триггеров - просто VIEW, где бы это поле считалось. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2002, 10:47:25 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
Не согласен, что поле Folder избыточно. В запросе узнавать тяжело для сервера, учитывая, что в приложении на одно обновление приходится 100 - 1000 чтений. А запрос будет вида: Код: plaintext 1. 2. 3. А вот и триггеры: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2002, 11:00:59 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
Друзья, а не проще ли так: триггер на вставку наращивает поле Folder на 1 (Default Folder`а - 0), а триггер на удаление - уменьшает его? Тогда в нем всегда будет храниться не только факт наличия "деток" (ненулевой Folder), а еще и их количество. Пример: CREATE TRIGGER table1_insert ON table1 FOR INSERT AS IF @@ROWCOUNT = 0 'блокирование ложн. срабатывания RETURN UPDATE table1 SET Folder = Folder + 1 FROM inserted INNER JOIN table1 ON inserted.ID_PARENT = table1.ID RETURN CREATE TRIGGER table1_delete ON table1 FOR DELETE AS IF @@ROWCOUNT = 0 RETURN UPDATE table1 SET Folder = Folder - 1 FROM deleted INNER JOIN table1 ON deleted.ID_PARENT = table1.ID RETURN Тут в конфе где-то неделю назад один умный человек дал ссылку на потрясающую статью (впечатляющего по крайней мере меня, не шибко зубрившего основы древовидных структур). Так вот структура типа обсуждающейся в этой теме (ID, ID_PARENT) называется "направленные графы". А вот в этой статье есть описание альтернативной структуры, позволяющей хранить те же иерархические зависимости, однако объекты в этой структуре оказываются связаными математической зависимостью, зная которую влегкую строится простой SELECT для получения на основе рассматриваемого узла любого вверх или вниз по иерархии. Я уже 3 года с "направленными графами" вобнимку, в моей структуре при добавлении объекта даже рассчитывается уровень вложенности тригером, все кульно, но: не нравится скорость "ползания" по дереву. Вот приду на работу с курсов, на которых я сейчас нахожусь - буду внедрять "альтернативу". Найдите ссылку на эту статью, почитайте, и попробуем вместе. Там есть кое-что, что мне не нравится, и я хочу применить комбинацию этих способов ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2002, 12:14:41 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
2 Dominic Ваш триггер не будет работать если например вставляется папа с двумя детьми, а удаляться будут по одному :) а статью Вы наверное эту имели ввиду деревья ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2002, 14:48:35 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
Эх... Нет в SQL рекурсивных запросов... Переходите на DB2 :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.07.2002, 06:19:16 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
а DB2 наверняка чего-нибудь другого нет :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.07.2002, 09:52:13 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
Вот еще статья по теме : Иерархические структуры, не требующие сопровождения Полюбопытсвуйте, коллеги. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.07.2002, 10:57:25 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
2 SergSuper Согласен. Вставлять "пачку" записей нельзя. Поэтому у себя в тригере вставил такую блокировку: ... AS DECLARE @rowcount INT SET @rowcount = @@ROWCOUNT IF @rowcount = 0 'блокирование ложн. срабатывания RETURN IF @rowcount > 1 BEGIN RAISERROR('Нельзя добавлять более 1 записи',16,1) RETURN END ... Самому-то мне все это не сильно нравится. Напомню, что решение организовать хранение объектов в иерархической структуре я принял в условиях лично моей низкой квалификации несколько лет назад, а когда "подрос" - приложение уже было запущено в эксплуатацию и было связано с другими приложениями по классификационным кодам (поле ID таблицы table1 имеет тип INT IDENTITY(1,1)) Приходилось выкручиваться "на ходу" и для основных сущностей предметной области создать и поддерживать реляционные (неиерархические структуры) тригерами table1. Размеры тригеров стали удручать: не меньше 500 строк для каждого события изменения данных. Кроме этого никак не удавалось найти приемлемого решения для события изменения атрибутов таких сущностей. Поэтому и нахожусь в поиске других решений. По поводу статьи - нет, не эта, хотя эта тоже крайне интересна, еще не прочитал. Я сейчас не на работе, где и закладка на статью и любовно распечатанная и пошитая копия. По поводу вставки пачки записей (целая ветка). Мне кажется, это можно решить только курсором, причем на содержимое поля ID должно быть наложено ограничение - по крайней мере ID "дочек" должны быть меньше ID своих "пап" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.07.2002, 12:11:47 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
2Gena G. Можно написать рекурсивную процедуру или триггер. Об этом часто задают вопросы начинающие. Когда у них получается, они радуются. Это очень плохой стиль программирования на SQL - языке структурированных запросов ; что-бы научится правильно программировать на нём, нужно годик заниматься только SQL-ем, близко не подходя к процедурным и объектным языкам, и тогда вырабатывается иммунитет от "рекурсий". Как - бы не был хорош DB2 со своими рекурсивными запросами, всё равно они, так-же как и запрос типа select t.ID, t.ParentID, t.Summa, case when exists(select * from MyTable t1 where t1.ParentID = t.ID) then 1 else 0 end as Folder from MyTable t очень неэффективны. Здесь предлагается нормальный выход - умеренная денормализация данных с поддержкой на триггере - вопрос только, как считать. Извините за эмоции - наболело... Я помню, в этом форуме один из таких начинающих возмущался - MS SQL Server недостаточно красиво, хуже чем Аксесс, рисует комбобоксы :-( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.07.2002, 12:15:54 |
|
||
|
И сново дерево
|
|||
|---|---|---|---|
|
#18+
2 Dominic По поводу вставки пачки записей (целая ветка). Мне кажется, это можно решить только курсором, причем на содержимое поля ID должно быть наложено ограничение - по крайней мере ID "дочек" должны быть меньше ID своих "пап" Нет, курсор здесь не нужен. Можно через временную таблицу - считать сколько дочек добавляется, а потом уже обновлять в основной. Как-то так(не проверял, только мысль пишу) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.07.2002, 15:23:32 |
|
||
|
|

start [/forum/topic.php?fid=46&msg=32036390&tid=1821832]: |
0ms |
get settings: |
8ms |
get forum list: |
11ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
63ms |
get topic data: |
9ms |
get forum data: |
4ms |
get page messages: |
35ms |
get tp. blocked users: |
1ms |
| others: | 228ms |
| total: | 365ms |

| 0 / 0 |
