-
Всем доброго времени суток!
есть таблица c иерархией (id integer, parent integer) как мне добавить внешний ключ: ALTER TABLE DETAIL ADD CONSTRAINT FK_DETAIL FOREIGN KEY (PARENT) REFERENCES DETAIL (ID) ON DELETE CASCADE ON UPDATE CASCADE;
так, чтобы я мог вставить потом корневой узел? ... Т.е. вопрос в том, как мне вставить корневой узел?
-
Например, со ссылкой в PARENT на свой же ID
-
> Сергей М. © (19.12.08 08:35) [1]
а как тогда оформить процедурку получения детей?
-
Добавь в таблицу поле LEVEL, формируй его в триггерах - для корней оно пусть будет = 0
Тогда
select * from MyTree where PARENT = SomeRootNodeID and LEVEL > 0
-
select *
from MyTree
where PARENT = SomeRootNodeID and LEVEL > 0
И что это даст? Нафиг эта проверка? Все, у кого парент = SomeRootNodeID, все будут иметь одно и тоже значение Level. Собственно, Parent.Level + 1 Выборку значений я бы через хп организовал с рекурсивным вызовом.
-
> Сергей М. © (19.12.08 10:07) [3]
не нра мне level: када апдейтить его буду, эт каким же триггер должон быть? и вообще: нихачу структуру БД приносить в жертву эээ.... чему? своему неумению? Как бы сделали Вы?
-
> Ega23 © (19.12.08 10:14) [4]
так и делаю
-
> не нра мне level: када апдейтить его буду, эт каким же триггер > должон быть?
Есть inserted, в нём есть ParentID. У Parent'а есть свой Level. Значит Level вставляемого будет Parent.Level + 1 только мне непонятно нафиг тут вообще Level.
-
> что это даст
Это даст выборку всех узлов, дочерних по отношению к корню с ID равным интересующему автора (SomeRootNodeID)
> Все, у кого парент = SomeRootNodeID, все будут иметь одно > и тоже значение Level. Собственно, Parent.Level + 1 >
Все верно. Это и подразумеваются.
> с рекурсивным вызовом. >
За каким тут рекурсия ?
Автора, насколько я понимаю, интересуют только "прямые" ветки, т.е. растущие непосредственно из интересующего его корня, а не вся прочая ботва, растущая в свою очередь из этих веток)
Доп.проверка на LEVEL > 0 нужна для исключения из выборки собственно корня, для которого согласно [1] условие PARENT = SomeRootNodeID окажется истинным.
-
> не нра мне level
Не не нра знач не нра. Наше дело предложить - ваше отказаться.
> када апдейтить его буду
При любом апдейте PARENT-поля этой записи. Ничего сложного.
> эт каким же триггер должон быть?
Пара доп.строчек добавляется - вот и все)
> Как бы сделали Вы?
Именно так я и сделал в некоторых своих вполне успешно работающих проектах.
-
> не нра мне level > >
А мне вот не нра null в PARENT у корневых узлов. На вкус и цвет, как говорится, ....) Хочешь - ешь, не хочешь - не ешь)
-
> Сергей М. © (19.12.08 10:24) [8]
да не, автора волнует все дети...
> Ega23 © (19.12.08 10:23) [7]
> Есть inserted, в нём есть ParentID. У Parent'а есть свой > Level. Значит Level вставляемого будет Parent.Level + 1
если будет не вставка, а редактирование уровня, то все немного усложнится, не так ли?
Ну да ладно, level я все равно не использую.
-
> автора волнует все дети
Ну тогда да, рекурсия нужна.
Но "все" - это ведь не дети, согласись ? Среди всех есть и внуки, и правнуки, и пра-пра-пра ..
Так что на будущее изволь уж быть точнее в формулировках)
-
> Сергей М. © (19.12.08 10:39) [12]
ок, просто думал, что это подразумевается
-
> foriegn keys (19.12.08 10:31) [11]
Зато имея LEVEL и еще одну вспомог.таблицу можно обойтись без рекурсии, что дает ощутимый выигрыш в производительности при выборках такого рода на большущих деревьях.
-
> foriegn keys (19.12.08 10:39) [13]
> это подразумевается
Увы и отнюдь)
-
> Это даст выборку всех узлов, дочерних по отношению к корню > с ID равным интересующему автора (SomeRootNodeID) >
Create table Test (
id int,
pid int,
aName varchar(32),
Level int,
constraint pk_test primary key (id),
constraint fk_test foreign key (pid) references Test (id)
);
insert into Test (id, pid, aName, level) Values (0, null, 'Root', 0);
insert into Test (id, pid, aName, level) Values (1, 0, 'Level1 Node1', 1);
insert into Test (id, pid, aName, level) Values (2, 0, 'Level1 Node2', 1);
insert into Test (id, pid, aName, level) Values (3, 0, 'Level1 Node3', 1);
insert into Test (id, pid, aName, level) Values (4, 1, 'Level2 Node1-1', 2);
insert into Test (id, pid, aName, level) Values (5, 1, 'Level2 Node1-2', 2);
insert into Test (id, pid, aName, level) Values (6, 1, 'Level2 Node1-3', 2);
Объясни мне смысл дополнительной проверки на Level в случае, когда я выбираю прямых "потомков" конкретного узла.
-
> Зато имея LEVEL и еще одну вспомог.таблицу можно обойтись > без рекурсии, что дает ощутимый выигрыш в производительности > при выборках такого рода на большущих деревьях.
Это от кучи нюансов зависит. Может быть и даст. А может и не даст.
-
> Ega23 © (19.12.08 10:44) [16]
см. [10]
-
> Ega23 © (19.12.08 10:45) [17]
Тебе видней)
-
> см. [10]
А как ты тогда вторичный ключ сам на себя навесишь? Или ты за ссылочной целостностью сам следишь?
-
> Ega23 © (19.12.08 10:57) [20]
> как ты тогда вторичный ключ сам на себя навесишь?
А что этому мешает ? Ничто.
> за ссылочной целостностью сам следишь?
А это без разницы. Можно и самому следить и автоматике довериться - зависит от требуемой прикл.логики.
-
> Ega23 © (19.12.08 10:57) [20]
Подозреваю, что ты как обычно упустил из виду IB6 - не знаю как в MSSQL, а в IB-совместимых серверах это успешно работает.
-
> Подозреваю, что ты как обычно упустил из виду IB6 - не знаю > как в MSSQL, а в IB-совместимых серверах это успешно работает.
В IB так можно? Странно... В MSSQL однозначно не сработает. Из-за той самой пресловутой ссылочной целостности. Я Root-запись вставить не смогу.
|