Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / И сново дерево / 12 сообщений из 12, страница 1 из 1
11.07.2002, 09:57:56
    #32036134
AlexanderVS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
Есть довольно стандартная таблица, реализующая хранение иерархической структуры:
ID,ParentID,Summa,Folder. Поле Folder должно хранить 1 -если данный элемент имеет деток, 0 - соответственно устанавливаем для конечных элементов.
Никак не могу придумать триггер, поддерживающий данное правило, при условии что дерево обновляется не построчно, а пакетной операцией.
Может кто подскажет как решить данную проблему?
...
Рейтинг: 0 / 0
11.07.2002, 10:45:33
    #32036158
ziktuw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
Убери поле Folder и проблема снимется сама собой. Оно избыточно, так как всегда можно узнать в запросе, есть ли детки или нет у конкретной ноды.
При желании можно написать вьюху, в которой это поле будет вычисленным
...
Рейтинг: 0 / 0
11.07.2002, 10:47:25
    #32036159
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
как-то так например можно

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, где бы это поле считалось.
...
Рейтинг: 0 / 0
11.07.2002, 11:00:59
    #32036166
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
Не согласен, что поле Folder избыточно. В запросе узнавать тяжело для сервера, учитывая, что в приложении на одно обновление приходится 100 - 1000 чтений. А запрос будет вида:
Код: plaintext
1.
2.
3.
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


А вот и триггеры:
Код: 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.
create trigger tU_MyTable on MyTable for update
as

if update(ParentID)
begin
	update MyTable
	set Folder =  1 
	from MyTable t
		join inserted i on i.ParentID = t.ID
		join deleted d on d.ID = i.ID and d.ParentID <> i.ParentID

	update MyTable
	set Folder =  0 
	from MyTable t
		join deleted d on d.ParentID = t.ID
	where not exists(select * from MyTable t1 where t1.ParentID = t.ID)
end
go

create trigger tI_MyTable on MyTable for insert
as

update MyTable
set Folder =  1 
from MyTable t
	join inserted i on i.ParentID = t.ID
go

create trigger tD_MyTable on MyTable for delete
as

update MyTable
set Folder =  0 
from MyTable t
	join deleted d on d.ParentID = t.ID
where not exists(select * from MyTable t1 where t1.ParentID = t.ID)
go
...
Рейтинг: 0 / 0
11.07.2002, 12:14:41
    #32036200
Dominic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
Друзья, а не проще ли так: триггер на вставку наращивает поле 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 года с "направленными графами" вобнимку, в моей структуре при добавлении объекта даже рассчитывается уровень вложенности тригером, все кульно, но: не нравится скорость "ползания" по дереву. Вот приду на работу с курсов, на которых я сейчас нахожусь - буду внедрять "альтернативу". Найдите ссылку на эту статью, почитайте, и попробуем вместе. Там есть кое-что, что мне не нравится, и я хочу применить комбинацию этих способов
...
Рейтинг: 0 / 0
11.07.2002, 14:48:35
    #32036251
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
2 Dominic
Ваш триггер не будет работать если например вставляется папа с двумя детьми, а удаляться будут по одному :)
а статью Вы наверное эту имели ввиду
деревья
...
Рейтинг: 0 / 0
12.07.2002, 06:19:16
    #32036390
Gena G.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
Эх... Нет в SQL рекурсивных запросов... Переходите на DB2 :)
...
Рейтинг: 0 / 0
12.07.2002, 09:52:13
    #32036405
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
а DB2 наверняка чего-нибудь другого нет :)
...
Рейтинг: 0 / 0
12.07.2002, 10:57:25
    #32036410
Jimmy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
Вот еще статья по теме : Иерархические структуры, не требующие сопровождения
Полюбопытсвуйте, коллеги.
...
Рейтинг: 0 / 0
12.07.2002, 12:11:47
    #32036423
Dominic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
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 своих "пап"
...
Рейтинг: 0 / 0
12.07.2002, 12:15:54
    #32036424
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
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 недостаточно красиво, хуже чем Аксесс, рисует комбобоксы :-(
...
Рейтинг: 0 / 0
12.07.2002, 15:23:32
    #32036475
SergSuper
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
И сново дерево
2 Dominic
По поводу вставки пачки записей (целая ветка). Мне кажется, это можно решить только курсором, причем на содержимое поля ID должно быть наложено ограничение - по крайней мере ID "дочек" должны быть меньше ID своих "пап"
Нет, курсор здесь не нужен. Можно через временную таблицу - считать сколько дочек добавляется, а потом уже обновлять в основной.
Как-то так(не проверял, только мысль пишу)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 ...
declare @t table(id int, fcount int)
insert @t
select t.ID, count(*)
from table1 t, inserted i
where i.ID_PARENT = t.ID 

UPDATE t 
SET Folder = Folder + fcount 
FROM table1 t, @t m
where m.id=t.ID
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / И сново дерево / 12 сообщений из 12, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]