Re: Иерархия объектов : cтруктура БД ?
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 04.04.03 05:43
Оценка: 41 (6)
Привет.

Приведу, в упрощенном виде, часть структуры ядра нашей БД

Таблица классов объектов БД
CREATE TABLE CLASS
(
 ID               T_CLASS       NOT NULL,
 TABLE_NAME       T_TABLE_ID    NOT NULL,
 SUPER_CLASS      T_INTEGER,
 
 COMMENT          T_VARCHAR_64,
 GEN              T_VARCHAR_32,/*ИМЯ ГЕНЕРАТОРА ИСПОЛЬЗУЕМОГО ДЛЯ ОБЪЕКТОВ ДАННОГО КЛАССА*/

 CONSTRAINT PK_CLASS       PRIMARY KEY (ID),
 CONSTRAINT FK_SUPER_CLASS FOREIGN KEY (SUPER_CLASS) REFERENCES CLASS (ID),
 
 FOREIGN KEY (TABLE_NAME) REFERENCES TABLE_NAME(ID)
);/*CLASS*/


Здесь ты регистрируешь классы своих объектов, назначая им уникальные номера (ID). Например


Таблица допустимых связей
CREATE TABLE POSSIBLE_OBJ_LINK
(
 OWNER_CLASS    T_CLASS NOT NULL,
 CHILD_CLASS    T_CLASS NOT NULL,

 CONSTRAINT PK_POSSIBLE_OBJ_LINK    PRIMARY KEY (OWNER_CLASS,CHILD_CLASS),
 FOREIGN KEY (OWNER_CLASS)    REFERENCES CLASS (ID),
 FOREIGN KEY (CHILD_CLASS)    REFERENCES CLASS (ID)
);


Здесь хранятся пары допустимых связей между классами объектов. В твоем случае, это будут записи вида:
0,0
0,100
100,200
200,200
200,300

Таблица объектов:
CREATE TABLE OBJECT
(
 ID             T_ID      NOT NULL,
 CLASS          T_CLASS   NOT NULL,

 OWNER          T_ID      NOT NULL,
 OWNER_CLASS    T_CLASS   NOT NULL,

 CONSTRAINT PK_OBJECT PRIMARY KEY (ID,CLASS),

 CONSTRAINT FK_OBJECT_TREE
         FOREIGN KEY (OWNER,OWNER_CLASS) REFERENCES OBJECT (ID,CLASS),
      
 CONSTRAINT FK_POSSIBLE_OBJECT_LINK
        FOREIGN KEY (OWNER_CLASS,CLASS) REFERENCES POSSIBLE_OBJ_LINK (OWNER_CLASS,CHILD_CLASS)

);/*OBJECT*/


При генерации базы в эту таблицу сразу запихивается объект (0,0), который завязан сам на себя.

Как видишь, FK_POSSIBLE_OBJECT_LINK контролирует допустимые связи между объектами разных классов.

Предвидя вопрос, а где же хранятся сами данные этих объектов, отвечу — не в таблице OBJECT. Для данных создаешь "производные таблицы", которые имеют PK(ID,CLASS), одновременно являющийся и FK на таблицу OBJECT. С помощью триггеров и каскадного удаления увязываешь время жизни записей в этих таблицах. Ну и вообщем дальше начинаешь парится с этим как-бы объектным представлением данных

Здесь я опустил кучу триггеров, которые проверяют отсутствие зацикливания, всякие фичи типа эмуляции каскадного удаления (например, удаляя том нужно удалить папки) и еще некоторые маленькие радости большой любви с базами данных
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Иерархия объектов : cтруктура БД ?
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 05.04.03 06:48
Оценка: 27 (3)
Здравствуйте, Poisson, Вы писали:

B>>Здесь парент указывает на эту же таблицу.

B>>Про потомков — check на уровне таблицы.
P>Да, спасибо, примерно так и сделаю. Только всю логику типа
P>удаления потомков при удалении родителя, проверки наличия
P>родителя при вставке пототка и т.п. пока придется делать на
P>уровне клиента, реализовать все это в БД пока не умею.

В терминах той структуры, которую я описал ниже, это делается элементарно .
Правда, элементарно для InterBase.

  1. Контролировать наличие родителя при вставке потомка — не обязательно. Это делается за счет FOREIGN KEY (который называется FK_OBJECT_TREE). Более того, в IB можно учудить вставку дочернего элемента не видя (в рамках транзакции) записи с родителем. Это нюансы IB и SNAPSHOT транзакций.
  2. Каcкадные удаления. Точнее их умуляция для дерева объектов. Общая схема такая.
    • Заводишь таблицу с атрибутами классов. Определяешь два вида атрибута: — удалять вложенные объекты (1) и самоудаляться при удалении родителя (2).
    • На таблицу OBJECT вешаешь триггер на удаление. Этот триггер проверяет атрибуты класса удаляемого объекта (класс объекта хранится в поле CLASS). Если у класса установлен атрибут (1), то триггер инициирует удаление всех вложенных объектов.
    • Второй триггер на удаление в OBJECT должен (при удалении объекта) удалять все его вложенные объекты, у класса которых есть атрибут (2)

Для твоей иерархии объектов том,папка(папка),элемент нужно назначить только один атрибут (2) для класса папки. Почему? Ответ прост
Делаешь один раз и потом пользуешься ... ну вообщем я эти пользуюсь уже пятый год

Исходные тексты триггеров выглядят так

/******************************************************************************/
/*               ТРИГГЕР КАСКАДНОГО УДАЛЕНИЯ ВЛОЖЕННЫХ ОБЪЕКТОВ               */
/* Определение признака каскадного удаления вложенных объектов                */

CREATE TRIGGER CASCADE_DELETE_CHILD_OBJ FOR OBJECT
 AFTER DELETE
 POSITION 110
AS
BEGIN
 /*CASCADE DELETE*/
 IF(EXISTS(SELECT * FROM CLASS_ATTRIBUTE CA
           WHERE CA.CLASS=OLD.CLASS AND CA.ATTRIBUTE=DB_CLS_ATTR_CASCADE_DELETE_CHILDS)) THEN
  DELETE FROM OBJECT WHERE OWNER=OLD.ID AND OWNER_CLASS=OLD.CLASS;
END!!

/******************************************************************************/
/*         ТРИГГЕР УДАЛЕНИЯ ОБЪЕКТОВ ПРИ УДАЛЕНИИ ПРЕДКА                      */

CREATE TRIGGER DELETE_WITH_OWNER_OBJ FOR OBJECT
 AFTER DELETE
 POSITION 100
AS
BEGIN
 DELETE FROM OBJECT OBJ
 WHERE OBJ.OWNER=OLD.ID AND OBJ.OWNER_CLASS=OLD.CLASS AND
       EXISTS(SELECT * FROM CLASS_ATTRIBUTE CA
              WHERE CA.CLASS=OBJ.CLASS AND CA.ATTRIBUTE=DB_CLS_ATTR_CASCADE_DELETE_WITH_OWNER);
END!!


DB_CLS_ATTR_CASCADE_DELETE_CHILDS и DB_CLS_ATTR_CASCADE_DELETE_WITH_OWNER это макросы с номерами атрибутов. Можно подставить явные цифры, например те же 1 и 2
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Иерархия объектов : cтруктура БД ?
От: Merle Австрия http://rsdn.ru
Дата: 04.04.03 15:06
Оценка: 15 (3)
Здравствуйте, ssm, Вы писали:

ssm>А "на пальцах" о транзитивном замыкании можно услышать?

Ну раз наш доблестный модератор пропал кудато, придется мне..
По простому, транзитивное замыкание — это когда X1=>Xn, потому что X1=>X2=> ... =>Xn (при n>0, иначе это уже рефлексивное замыкание)
В данном случае _MM_ видимо имел ввиду, что можно построить таблицу в которой будут указаны предки и все потомки принадлежащие данному предку, таким образом можно одним запросом выбрать нужное поддерево.
Подробнее об этом можно почитать в статье на этом сайте (она правда не отличается излишней подробностью и точностью, но утверждать не буду, давно читал) или поискать в инете на тему отображения деревьев на реляционную структуру. .
Мы уже победили, просто это еще не так заметно...
Re: Иерархия объектов : cтруктура БД ?
От: _MarlboroMan_ Россия  
Дата: 03.04.03 20:14
Оценка: 26 (2)
Здравствуйте, Poisson, Вы писали:

[skip]

для начала я бы построил такое дерево:
id | parent_id | object_id | type_id |

где id <-> parent_id — задают собственно иерархию, object_id — ссылка на объект (на запись в соответствующей таблице), type_id — ссылка на тип (например таблицу типов или константа) объекта.

связка object_id — type_id является уникальной в пределах иерархии и однозначно задает объект.

вот теперь объекты уже можно хранить в разных таблицах.

при попытке прицепить нечто как "ребенка" к данному "папе" — проверяем тип папы и делаем выводы о допустимости такого прицепления. ну и т.д.

полезность:
для облегчения жисти (и избавления от рекурсии при разборе дерева) можешь еще построить транзитивное замыкание (ТЗ) этого дерева.

ТЗ усложнит вставку и копирование веток, но облегчит тебе жисть при удалении поддеревьев, а так же при навигации по дереву и определении всяких полезностей: типа всех потомков данного элемента, ветвистости дерева, входимости данного элемента в заданное поддерево и т.д.
... << RSDN@Home 1.0 beta 6a >>

— сколько программистов надо чтобы заменить сгоревшую лампочку?
— сколько не бери, а лампочку не поменять — проблема аппаратная, программным путем не решается...
Re[5]: SHAPSHOT и деревья
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 06.05.03 08:02
Оценка: 18 (1)
Здравствуйте, ssm, Вы писали:

КД>Более того, в IB можно учудить вставку дочернего элемента не видя (в рамках транзакции) записи с родителем. Это нюансы IB и SNAPSHOT транзакций.


ssm>Меня терзают смутные сомнения


В плане?
  1. старт первой транзакции (t1)
  2. старт второй (SNAPSHOT) транзакции (t2)
  3. t1: вставка родителя (ну или мастер-запись, кому как нравится)
  4. t1: commit
  5. t2: вставка потомка этого родителя. Триггер, который сработает на вставку этой записи, родителя не увидит — он же тоже работает в SNAPSHOT'e и починяется его законам.
  6. t2: commit
Все дело в том, что индексы (и FK-ключи тоже) у IB работают вне контекста транзакции.
Можешь попробовать сам. Мне это точно не приcнилось
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Иерархия объектов : cтруктура БД ?
От: Poisson Россия  
Дата: 03.04.03 18:45
Оценка:
Учитывая, что в плане разработки БД я собак не ел , посоветуйте,
как лучше реализовать структуру БД (в частности, в Access),
предоставляющую сведения о иерархии "том/папка/элемент". Точнее, есть три
типа объектов :

— элемент, может находиться в томе или в папке, не может иметь потомков
— папка, может в находиться в томе или папке
— том, тома находятся на верхнем уровне иерархии

У каждого объекта есть имя (строка).

Очевидая мысль -- три таблицы на каждый тип объектов, дополнительное
поле "родитель" для папки и элемента. Но поскольку элемент, например, может
быть как в папке, так и в томе, то ввести связь "один ко многим" с
проверкой целостности вроде как не получится.. Короче, ваши предложения?
Re: Иерархия объектов : cтруктура БД ?
От: bizhan  
Дата: 03.04.03 20:18
Оценка:
Привет,

P>Короче, ваши предложения?


Если он не может находится и там и там одновременно, то одна таблица:

table element (
    id integer, primary, not null                 
    type integer, not null
    title varchar(xxx),
    parent integer, fk, null)


Здесь парент указывает на эту же таблицу.

Про потомков — check на уровне таблицы.

Если же элемент находится и в папке и в томе, то делаем _два_ парента.

Либо делаем еще одну табицу рядом:

table element_releation (
   id, primary, fk, not null
   parent_id, primary, fk, not null
)

Составной примари. Оба fk — на element.id.

Поля интерпретировать в зависимости от того, кто про кого знает.
Если дите про родителя, то
id — id дитя (элемента), parent_id — id родителя (папки или тома)
Если родитель про дите, то наоборот.

В случае двух таблицк получаем, что элемент может входить во много папок или во много томов.

Если это надо ограничить — входить только в одну папку, то делаем чуть по другому:

table element_releation_constraint (
  id, primary, fk, not null
  type, primary, fk, not null
  parent_id, fk, not null)


Составной примари: id+тип дают нам то, что надо. Для данного эелемнта и данного
типа етсь одна и только одна папка.

Либо играться с unique разными способами.

Павел
Re: Иерархия объектов : cтруктура БД ?
От: Work-S Россия  
Дата: 04.04.03 05:37
Оценка:
Здравствуйте, Poisson, Вы писали:


P>Учитывая, что в плане разработки БД я собак не ел , посоветуйте,

P>как лучше реализовать структуру БД (в частности, в Access),
P>предоставляющую сведения о иерархии "том/папка/элемент". Точнее, есть три
P>типа объектов :

P>- элемент, может находиться в томе или в папке, не может иметь потомков

P>- папка, может в находиться в томе или папке
P>- том, тома находятся на верхнем уровне иерархии

P>У каждого объекта есть имя (строка).


P>Очевидая мысль -- три таблицы на каждый тип объектов, дополнительное

P>поле "родитель" для папки и элемента. Но поскольку элемент, например, может
P>быть как в папке, так и в томе, то ввести связь "один ко многим" с
P>проверкой целостности вроде как не получится.. Короче, ваши предложения?

Так сделай связь "много ко многим". Насколько я знаю, это делается через дополнительную таблицу. A->C<-B => A<->B
Re[2]: Иерархия объектов : cтруктура БД ?
От: ssm Россия  
Дата: 04.04.03 07:19
Оценка:
Здравствуйте, _MarlboroMan_, Вы писали:

А "на пальцах" о транзитивном замыкании можно услышать?

Спасибо.
Re[2]: Иерархия объектов : cтруктура БД ?
От: Poisson Россия  
Дата: 04.04.03 17:22
Оценка:
Здравствуйте, bizhan, Вы писали:

B>Привет,


B>Если он не может находится и там и там одновременно, то одна таблица:

Не может (структура наподобие простейшей файловой системы безо всяких ссылок)

B>table element (

B> id integer, primary, not null
B> type integer, not null
B> title varchar(xxx),
B> parent integer, fk, null)

B>Здесь парент указывает на эту же таблицу.

B>Про потомков — check на уровне таблицы.
Да, спасибо, примерно так и сделаю. Только всю логику типа
удаления потомков при удалении родителя, проверки наличия
родителя при вставке пототка и т.п. пока придется делать на
уровне клиента, реализовать все это в БД пока не умею. ;)
Re[3]: Иерархия объектов : cтруктура БД ?
От: bizhan  
Дата: 05.04.03 10:55
Оценка:
Привет,

B>>Если он не может находится и там и там одновременно, то одна таблица:

P>Не может (структура наподобие простейшей файловой системы безо всяких ссылок)

Помни, что в современных ОС можно сделать subst. Тогда один и тот же файл будет в разных местах.
а есть еще hard/soft линки..

B>>table element (

B>> id integer, primary, not null
B>> type integer, not null
B>> title varchar(xxx),
B>> parent integer, fk, null)

B>>Здесь парент указывает на эту же таблицу.

B>>Про потомков — check на уровне таблицы.
P>Да, спасибо, примерно так и сделаю. Только всю логику типа
P>удаления потомков при удалении родителя, проверки наличия
P>родителя при вставке пототка и т.п. пока придется делать на
P>уровне клиента, реализовать все это в БД пока не умею.

А зачем? Когда создаешь fk для parent, можно указать on delete cascase.
Тогда при удалении записи, атвоматом будут удалены его дети.
Проверка наличия сделается сама за счет fk, об том писали.

Павел
Re: Иерархия объектов : cтруктура БД ?
От: Akzhan Россия http://www.akzhan.midi.ru/devcorner/
Дата: 04.05.03 13:38
Оценка:
Здравствуйте, Poisson, Вы писали:

http://www.akzhan.midi.ru/devcorner/articles/DDP-Accounting-scheme-example-rus.html

http://www.akzhan.midi.ru/devcorner/articles/DDP-Representation-of-an-absent-information-rus.html

Кратко — достаточно реляционки. С учётом Вашей задачи всё будет быстро.
Например, уровень узла считается очень быстро как
select count(*) from AnAccountAndItsAncestors where AccountId = @AccountId
С уважением,
Акжан, http://www.akzhan.midi.ru/devcorner/ — мой уголок разработчика
Re[4]: Иерархия объектов : cтруктура БД ?
От: ssm Россия  
Дата: 06.05.03 07:45
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>Более того, в IB можно учудить вставку дочернего элемента не видя (в рамках транзакции) записи с родителем. Это нюансы IB и SNAPSHOT транзакций.


Меня терзают смутные сомнения
Re[6]: SHAPSHOT и деревья
От: ssm Россия  
Дата: 06.05.03 08:14
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>Все дело в том, что индексы (и FK-ключи тоже) у IB работают вне контекста транзакции.

КД>Можешь попробовать сам. Мне это точно не приcнилось

Вот это да!!! Так это только клоны IB себя так ведут?
Re[4]: Иерархия объектов : cтруктура БД ?
От: Akzhan Россия http://www.akzhan.midi.ru/devcorner/
Дата: 06.05.03 11:23
Оценка:
Здравствуйте, Merle, Вы писали:

ssm>А "на пальцах" о транзитивном замыкании можно услышать?


Кстати, меня всегда умиляла эта статья и вообще реализация иерархических структур через это самое.

Обычное представление через таблицу объектов, таблицу подобъектов (унаследована от объектов) и служебную таблицу (объект и все его владельцы) работает более эффективно, особенно в случае модификации дерева.

часто таблицу объектов и таблицу подобъектов реализуют как единую таблицу (id, parentid, data), но это некрасиво.
С уважением,
Акжан, http://www.akzhan.midi.ru/devcorner/ — мой уголок разработчика
Re[5]: Иерархия объектов : cтруктура БД ?
От: ssm Россия  
Дата: 06.05.03 11:26
Оценка:
Здравствуйте, Akzhan, Вы писали:

A>часто таблицу объектов и таблицу подобъектов реализуют как единую таблицу (id, parentid, data), но это некрасиво.


Зато просто и сердито
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.