Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > БД в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.03.2009, 13:26   #1
Cerber24
Пользователь
 
Регистрация: 07.05.2008
Сообщений: 38
По умолчанию Дерево в FireBird

Доброго времени суток, такая проблема нужно сделать иерархическую структуру(дерево). В базе есть поле содержащее указатели нахождения объектов в дереве, выглядит примерно так 1.3.5.3 для каждого объекта. Как организовать дерево на сервере в хранимой процедуре, ну или на клиенте(точно не знаю, как лучше будет). пользуясь вот этими указателями 1.3.5.3. (FireBird 2.1, Delphi 7 используемые компоненты IBX) Буду благодарен любой помощи...

Последний раз редактировалось Cerber24; 11.03.2009 в 13:38.
Cerber24 вне форума Ответить с цитированием
Старый 11.03.2009, 13:56   #2
_Engine_
Форумчанин
 
Регистрация: 29.06.2008
Сообщений: 603
По умолчанию

Я бы делал примерно так:
Список полей:
ID
ID_Parent
ID_Parent_ID
....

где ID_Parent - ссылка на ID, а ID_Parent_ID - номер в ветке
только надо будет триггер на вставку прописать, чтобы инкрементил значение ID_Parent_ID, в принципе не сложно, и при правильных индексах работать быстро будет.
_Engine_ вне форума Ответить с цитированием
Старый 11.03.2009, 13:57   #3
Антон Ю.Б.
Форумчанин
 
Регистрация: 03.01.2009
Сообщений: 116
По умолчанию

Ну вообще для БД классическим вариантом является наличие в таблице полей ID_, PARENT_ID_ . Именно под такое заточено и большинство визуальных контролов для отображения таких структур. А уж 1.3.5.3 можно собирать хранимой процедурой при необходимости. Из удобных контролов могу посоветовать dbGridEh+MemTableEh (EhLib) или VirtualTreeView (точнее, его порт для BD. Там, правда, ориентировано на FIBPlus и есть некоторые конфликты из-за разности версий, но могу переслать уже поправленные исходники).
Антон Ю.Б. вне форума Ответить с цитированием
Старый 11.03.2009, 14:17   #4
Cerber24
Пользователь
 
Регистрация: 07.05.2008
Сообщений: 38
По умолчанию

Дело в том, что структуру базы по возможности лучше не менять, а так как у меня в базе с такими указателями реально сделать? если можно наброски процедуры напишите, пытаюсь воспользоваться вот этим IBXExTrees5.0 компонентом. если что мыло вот Cerber24@km.ru.

Кнопку "Правка" видите?
Она как раз для редактирования своих сообщений.
А плодить подряд - наказуемо...

Последний раз редактировалось mihali4; 11.03.2009 в 14:32.
Cerber24 вне форума Ответить с цитированием
Старый 11.03.2009, 14:21   #5
Антон Ю.Б.
Форумчанин
 
Регистрация: 03.01.2009
Сообщений: 116
По умолчанию

Cerber24, у меня реализовано вот так:
Цитата:
CREATE TABLE TRAIN_TREE (
ID_ Integer NOT NULL,
ORDER_ Integer NOT NULL, //порядок узла в своей группе
PARENT_ID_ Integer, //идентификатор родительского узла
PATH_ Varchar(100),
...
CONSTRAINT PK_TRAIN_TREE PRIMARY KEY (ID_)
);

CREATE OR ALTER PROCEDURE GET_PATH_FOR_TRAIN_NODE (NODE_ID_ Integer)
returns (RES Varchar(100))
AS
declare variable TMP1_ Varchar(100);
declare variable I Integer;
declare variable J Integer;
declare variable K Integer;
begin
select first 1 PARENT_ID_,ORDER_ from TRAIN_TREE WHERE ID_=:NODE_ID_ into :I,:J;
if (I=0) then
begin
RES=CAST(J as VARCHAR(100))||'.';
end
else
begin
select RES from GET_PATH_FOR_TRAIN_NODE(:I) into :TMP1_;
RES=TMP1_||CAST(J as VARCHAR(100))||'.';
end
J=STRLEN(RES);
I=1;
K=0;
while (i<=j) do
begin
TMP1_=SUBSTR(RES,I,I);
if (TMP1_='.') then K=K+1;
I=I+1;
end
J=1;
WHILE (J<K) do
begin
RES=' '||RES;
J=J+1;
end
suspend;
end

update TRAIN_TREE TT set PATH_=(select RES from GET_PATH_FOR_TREE_NODE(TT.ID_))
Из особенностей здесь то, что мне путь к узлу нужен был с выравниванием пробелами, поэтому там используются две UDF ф-ии. Несложно набросать и процедуру, что будет получать PARENT_ID_ по пути узла, если у Вас в таблице пока только путь:

Цитата:
DECLARE EXTERNAL FUNCTION STRPOS
CSTRING(16384),CSTRING(16384)
RETURNS Integer BY VALUE
ENTRY_POINT 'fn_strpos'
MODULE_NAME 'rfunc'

DECLARE EXTERNAL FUNCTION SUBSTR
CSTRING(255),Smallint,Smallint
RETURNS CSTRING(255) FREE_IT
ENTRY_POINT 'IB_UDF_substr'
MODULE_NAME 'ib_udf'

CSTRING(32767)
RETURNS Integer BY VALUE
ENTRY_POINT 'IB_UDF_strlen'
MODULE_NAME 'ib_udf'

CREATE OR ALTER PROCEDURE GET_NODE_INFO (NODE_ID_ Integer)
returns (RES_ORDER_ Integer,
RES_PARENT_ID_ Integer)
AS
declare variable TMP1_ Varchar(100);
declare variable I Integer;
begin
RES_ORDER_=null;
RES_PARENT_ID_=null;
select first 1 PATH_ from TRAIN_TREE WHERE ID_=:NODE_ID_ into :TMP1_;
TMP1_=TRIM(TMP1_);
I=STRLEN(TMP1_)-1;
while ((i>0)and(SUBSTR(TMP1_,I,I)<>'.'))d o
begin
I=I-1;
end
if (I>0) then
begin
RES_ORDER_=CAST(SUBSTR(TMP1_,I+1,ST RLEN(TMP1_)-1) AS INTEGER);
TMP1_=SUBSTR(TMP1_,1,I);
select first 1 ID_ from TRAIN_TREE WHERE TRIM(PATH_)=:TMP1_ into :RES_PARENT_ID_;
end
suspend;
end
Проект тот делался давно, а в FB 2.1. появились BUILT-IN функции, что позволят обойтись и без UDF: CHAR_LENGTH, POSITION, OVERLAY

Последний раз редактировалось Антон Ю.Б.; 11.03.2009 в 14:46.
Антон Ю.Б. вне форума Ответить с цитированием
Старый 11.03.2009, 15:37   #6
Cerber24
Пользователь
 
Регистрация: 07.05.2008
Сообщений: 38
По умолчанию

Может я чего-то недопонял, если что извините. Здесь реализовано обычное дерево, как мне подступится вот с этим полем к нему?(1.3.5.3 типо у первого родителя третий потомок, далее идём по нему, у него есть 5 ребёнок идём по нему, и уже у этого потомка есть 3 потомок-требуемый объект)
Cerber24 вне форума Ответить с цитированием
Старый 11.03.2009, 17:46   #7
Антон Ю.Б.
Форумчанин
 
Регистрация: 03.01.2009
Сообщений: 116
По умолчанию

В моей терминологии (обозначениях) у Вас есть сейчас поле PATH_ со значениями типа '1.3.1.7'. Наверное у Вас есть и поле ID_ . Заводите еще два целочисленных поля ORDER_ и PARENT_ID_. Создайте хранимую процедуру (конец моего прошлого ответа), которая поможет Вам с помощью запросов типа
update TRAIN_TREE TT set ORDER_=(select RES_ORFER_ from GET_NODE_INFO(TT.ID_))
заполнить эти два новых поля. После этого можете спокойно цеплять эту таблицу (или запросы из нее) к контролам, которые основаны на традиционном представлении дерева через поля (ID_,PARENT_ID_).

P.S. Обратите внимание, что моя процедура составлена в предположении формата номеров, заканчивающихся точкой, а не цифрой, то есть обход строки и выделение подстрок надо немного поправить.
Антон Ю.Б. вне форума Ответить с цитированием
Старый 12.03.2009, 12:06   #8
Cerber24
Пользователь
 
Регистрация: 07.05.2008
Сообщений: 38
По умолчанию

Цитата:
Name Type Описание
C_OBJECT INTEGER Код
R_ROOT INTEGER Ссылка на "корневую" запись

GLOBTYPE INTEGER Глобальный тип объекта. Типы находятся в файле AukTypes.

OBJTYPE INTEGER Тип объекта. Типы находятся в файле AukTypes

OBJINDEX VARCHAR(32) Индекс объекта

CHILDCOUNT INTEGER Количество дочерних объектов

SHORTNAME VARCHAR(60) Краткое название объекта

FULLNAME VARCHAR(240) Полное название

OBJBODY BLOB SUB_TYPE 0 SEGMENT SIZE 80 Тело объекта (его содержание)

ST_REFS1 VARCHAR(50) 1-я строка для поиска позиции «от» (до перевода строки)

ST_REFS2 VARCHAR(50) 2-я строка для поиска позиции «от» (после перевода строки)

WIDTH_VIEWER INTEGER Ширина компонента FrameViewer во время отметки позиции «от»

FNAME_LIT VARCHAR(50) Название файла ресурса с расширением

REF_NAME VARCHAR(50) Ссылка на ресурс в виде HTML^Res_000.GDB$118#0
(тип ресурса^файл ресурса$id в файле ресурса#начальная позиция в файле ресурса)

ST_REFS1_TO VARCHAR(50) 1-я строка для поиска позиции «до» (до перевода строки)

ST_REFS2_TO VARCHAR(50) 2-я строка для поиска позиции «до» (после перевода строки)

WIDTH_VIEWER_TO INTEGER Ширина компонента FrameViewer во время отметки позиции «до»

Вот одна из таблиц, поле где содержится 1.3.5.3 OBJINDEX

Последний раз редактировалось Cerber24; 12.03.2009 в 13:22.
Cerber24 вне форума Ответить с цитированием
Старый 12.03.2009, 13:33   #9
Антон Ю.Б.
Форумчанин
 
Регистрация: 03.01.2009
Сообщений: 116
По умолчанию

Cerber24, Вы даже название этого поля не привели OBJINDEX, видимо? Заметьте, что Вы даже проблему толком не обозначили. Только по косвенным признакам (упоминание IBXExTrees5.0) можно сделать вывод, что Вам нужно наглядное представление этой иерархической структуры в каком-то контроле клиента.

Ну хорошо, есть у Вас таблица, что Вам непонятно-то из советов? Контролы традиционно работают со схемой (сами выстраивают и отображают дерево), когда в таблице есть два поля для представления дерева - код записи (ID_ в прежних обозначениях) и код родительской записи (PARENT_ID_), если надо представлять структурный номер, то нужно еще поле порядкового номера в своей группе (ORDER_) и поле под структурный номер (PATH_). Без последнего поля можно обойтись и составлять его хранимой процедурой (разумеется, если таблица с данными не очень велика по объему). У Вас сейчас есть, видимо, только поле с кодом записи (C_OBJECT) и поле со структурным номером (OBJINDEX). Создайте поле под код родительской записи и поле под порядок узла в своей группе. Создайте хранимую процедуру для заполнения новых полей, заполните эти поля и спокойно цепляйте таблицу к контролу указав ему поля ID_, PARENT_ID_ и отображаемые информационные поля.

Мне либо неясна Ваша проблема, либо неясно как еще более подробно и ясно изложить ее решение

Примечание: в хранимой процедуре я забыл обработать ситуацию с корневым узлом, ему в качестве PARENT_ID_ в зависимости от соглашений может указываться 0,-1 или null (иногда это явно прописывается в свойствах контрола).
Антон Ю.Б. вне форума Ответить с цитированием
Старый 06.04.2009, 20:55   #10
Cerber24
Пользователь
 
Регистрация: 07.05.2008
Сообщений: 38
По умолчанию

Спасибо всем, кто откликнулся, помогите плиз с такой проблемкой, как узнать ID элемента (в моем примере C_OBJECT) выбранного мышкой в TreeFiew???
Cerber24 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Firebird vs Delphi HELP! paSHIZ БД в Delphi 4 13.01.2009 12:19
FireBird Д'якон БД в Delphi 2 04.12.2008 11:15
FireBird 1.5.4 Nikola__ БД в Delphi 2 17.11.2008 14:42
TSQLConnection и FireBird Abercrombie БД в Delphi 5 12.02.2008 14:11
округление в Firebird shurik_7866 БД в Delphi 0 05.07.2007 11:10