Правильная ссылка на эту страницу
http://az-design.ru/Support/DataBase/DBTree2/2100.shtml

Простая (одинарная) древовидная структура

Архангельский Андрей

Таблицы

       Чтобы подойти к построению "деревьев", мы должны рассмотреть что представляет собой реляционная таблица.


Рис.1-1 Реляционная таблица

       Таблица имеет структуру, т.е. состоит из полей, описывающих характеристики некоего объекта. Записи такой таблицы представляют собой характеристики экземпляров одного и того же типа. В классической теории РБД считается что записи располагаются в таблице в произвольном порядке и только уникальный идентификатор (или уникальный набор идентификаторов) позволяет однозначно выбрать ту или иную запись.
       Если мы может построить связи между таблицами, используя ограничение внешнего ключа (FK), то почему бы нам не построить такую же связь внутри одной таблицы. Таким образом можно хранить в таблице не только характеристики экземпляров, но и информацию о связях между этими экземплярами. Типичный пример необходимости таких связей — таблица "Люди". Так как каждый человек имеет родителей, то эту информацию также необходимо отразить в таблице.
       Структура такой таблицы будет выглядеть следующим образом:


Рис.1-2 Связь внутри одной таблицы

Однако с помощью SQL таблицы описывать немного легче:

Create table People (
       PID        Integer not null primary key,
       Parent     Integer,
       Atribut1   Char(30),
       Atribut2   Char(100),
       Atribut3   Char(50));
Commit;
Alter table People add foreign key (Parent) 
      references People on update cascade;
Commit;

       Первая проблема, которая возникает в этом случае — может ли поле Parent иметь значение Null?
       Если может, то могут быть проблемы связанные с неадекватным поведением в некоторых случаях. Вообще по возможности нужно избегать значения Null, по крайней мере в ссылках.
       Если поле Parent не может иметь значение Null, то до ввода первой записи должна существовать запись с родителем — т.е. возникает проблема "Курицы и яйца". Однако, эта проблема решается просто — выбирается значение PID, которое принимается как "Корневой родитель", например 0. И до создания триггеров в таблицу вводиться запись:

Insert into People(PID,Parent) values(0,0);

       Т.е. первая запись содержит одинаковые значения полей PID и Parent.
       Этот вариант прекрасно работает в FireBird 1.53, Firebird 2.0, но не в InterBase 7.5 — здесь есть особенности реализации. IB7.5 требует чтобы запись со значением PID=0 была вставлена ДО добавления FK для организации дерева. Следовательно скрипт должен быть записан так:

Create table People (
       PID        Integer not null primary key,
       Parent     Integer,
       Atribut1   Char(30),
       Atribut2   Char(100),
       Atribut3   Char(50));
Commit;
Insert into People(PID,Parent) values(0,0);
Commit;
Alter table People add foreign key (Parent) 
      references People on update cascade;
Commit;

       Вопрос о выборе значения PID не случайный — разработчик может по разному формировать уникальные значения этого поля. Это могут быть генераторы или какая-нибудь хеш-функция. Более подробно об этом ниже.

© 01.08.2009, Архангельский А.Г.

<<Пред. Оглавление
Начало раздела
След.>>




Дата последнего изменения:
Thursday, 21-Aug-2014 09:10:44 MSK


Постоянный адрес статьи:
http://az-design.ru/Support/DataBase/DBTree2/2100.shtml