Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.08.13;
Скачать: CL | DM;

Вниз

Подскажите как сделать вывод базы данных в виде дерева   Найти похожие ветки 

 
ceval ©   (2006-06-06 15:07) [0]

Здравствуйте
Подскажите как сделать вывод базы данных в виде дерева
например есть файл mdb и из него будут браться данныя
что то вроде этого (Главная - Отдел- Подразделения)
[]
|
[]___
|  |  |
[] [][]


 
Сергей М. ©   (2006-06-06 15:12) [1]


> как сделать вывод базы данных в виде дерева


Никак.


 
Sergey13 ©   (2006-06-06 15:15) [2]

DBTreeView - можно искать готовые, можно самому делать.


 
ANB ©   (2006-06-06 15:16) [3]

Это смотря чем и кто БД создавал. Используй оракл, он, правда не увидит твою mdb, зато в нем connect by есть.


 
Ega23 ©   (2006-06-06 15:21) [4]


> Никак.


Не ври. Хочешь выведу?


 
Ega23 ©   (2006-06-06 15:22) [5]

Есть компонент, писал сам, но функциональность специфичная, под общие нужды не заточена.


 
ANB ©   (2006-06-06 15:24) [6]


> Ega23 ©   (06.06.06 15:22) [5]

Ну ты крут. Просто взять и вывести mdb файл в виде дерева.
Кстати, судя по всему у автора обычная связка мастер-детал, только БД он скорее всего рисовать еще не начинал, иначе догадался бы запостить структуру таблиц.


 
Ega23 ©   (2006-06-06 15:26) [7]


> Ну ты крут. Просто взять и вывести mdb файл в виде дерева.


Согласись, что запрос, возвращающий вообще всю базу, написать можно. Сложно, геморно и главное - никому не нужно. Но можно.


 
Сергей М. ©   (2006-06-06 15:43) [8]


> Ega23 ©   (06.06.06 15:21) [4]


Валяй..


 
Курдль ©   (2006-06-06 15:45) [9]

1. Упорядочить (рекурсия)
2. Выявить уровни (там же)
3. Отобразить (tree list)


 
Ega23 ©   (2006-06-06 15:53) [10]


> Валяй..


Давай запрос. KeyField, ParentKeyField, DisplayField, ImageField.
Можно и другие, но этого достаточно.


 
Курдль ©   (2006-06-06 16:00) [11]


> DisplayField, ImageField

И шо оно туда выдаст? Таки настоящие деревья? 8-()


 
Ega23 ©   (2006-06-06 16:02) [12]


> И шо оно туда выдаст? Таки настоящие деревья? 8-()

DisplayField - это то, что в TTreeNode.Text будет
ImageField - поле с BLOB, пока bmp 16х16. Будет "присовокуплена к узлу" дерева.


 
Курдль ©   (2006-06-06 16:06) [13]

Думаю, что Сергей М. ©   (06.06.06 15:43) [8] имел в виду то, что результат запроса будет линейный, как ни старайся. Т.е. просто набор записей :(
Если ты имеешь в виду, что нарисуешь деревянно-упорядоченный запрос (не функцию и не на оракле), то мне тоже интересно. Можно без картинок :)


 
Сергей М. ©   (2006-06-06 16:12) [14]


> Ega23 ©   (06.06.06 15:53) [10]


Запросы эти сам строй) .. Оно мне надо ?

До кучи сразу объясняй автору, чем отличается база данных от табличных (и иных) объектов в ее составе.


 
Ega23 ©   (2006-06-06 16:12) [15]


> Если ты имеешь в виду, что нарисуешь деревянно-упорядоченный
> запрос (не функцию и не на оракле), то мне тоже интересно.
>


Я с MSSQL работаю. А имел ввиду, что написал компонент TDBTreeView. Для работы ему надо задать все эти поля [10] + TDataSource.


 
Курдль ©   (2006-06-06 16:16) [16]


> А имел ввиду, что написал компонент TDBTreeView.


А знаменитую функцию IncDay() тоже ты написал? :)
Этой заразы полно: dxDBTreeList, cxDBTreeView, ehDBTree (типа того).


 
Ega23 ©   (2006-06-06 16:32) [17]


> А знаменитую функцию IncDay() тоже ты написал


Нет. Но она у меня есть.


> Этой заразы полно: dxDBTreeList, cxDBTreeView, ehDBTree
> (типа того).


Первое денег стоит. Немалых. Про вторые - ничего не знаю. А технологию создания ДБ-компонентов всё равно надо было поднимать: уж больно специфичные компоненты получались. Вот на дереве и тренировался...


 
Курдль ©   (2006-06-06 16:50) [18]


> Вот на дереве и тренировался...


Да уж... Я как-то тоже тренировался. Осваивал двойную буферизацию, drag-n-drop скроллирование и прочую хрень. Ничего так контрол получился - без тормозов и глюков. Но он принес больше пользы в плане ООП. Столько типов и коллекций в одном компоненте мне раньше не приходилось делать...


 
Ega23 ©   (2006-06-06 17:01) [19]


> Но он принес больше пользы в плане ООП.


Ну, скажем, мне он помог понять тонкости работы DB-Aware компонентов в Delphi.


 
Amoeba ©   (2006-06-06 17:16) [20]


> Этой заразы полно: dxDBTreeList, cxDBTreeView, ehDBTree
> (типа того).

Даже в JVCL есть (взят из RALib). Очень приличный компонент, позволяет все редактирование непосредственно в дереве, включая перемещение ветвей. С моей подачи в 3-й версии библиотеки то пофиксили один нехороший баг.


 
ANB ©   (2006-06-06 17:50) [21]


> Ega23 ©   (06.06.06 15:26) [7]

Это ежели в mdb гарантировано база mssql и не кривая. :)


 
ceval ©   (2006-06-07 20:22) [22]

спасиба буду разбираться
может стоит попробывать тогда использываться какой нибудь DBTreeView и db


 
kaif ©   (2006-06-07 21:50) [23]

Я обычно делаю дерево так:
Беру обычный TTreeView.
На событие OnCollapse удаляю все дочерние Nodes текущего Node.
На событие OnExpand создаю дочерние Nodes одним уровнем ниже для распахиваемого пункта, обращаясь всякий раз SQL-запросом к базе данных. При создании дочернего Node, если пункт имеет в базе дочерние (HAS_CHILDREN = 1), то устанавливаю для таких принудительно свойство Node.HasChildren := True.
При запуске программы создаю корневой Node, запросив одну строку из базы данных.
ID храню в свойстве Node.Data, явно приведя к Pointer.

Структуру таблицы делаю примерно такую:
ID INTEGER,
PARENT_ID INTEGER,
NAME VARCHAR(50),
HAS_CHILDREN INTEGER

В триггере AFTER DELETE делаю:
IF (NOT EXISTS(SELECT ID FROM MyTable WHERE ID = OLD.PARENT_ID) THEN
UPDATE MyTable SET HAS_CHILDREN = 0;

В триггере AFTER INSERT делаю:
UPDATE MyTable SET HAS_CHILDREN = 1;

В триггере AFTER UPDATE делаю и то и другое вместе:
IF (OLD.PARENT_ID <> NEW.PARENT_ID) THEN
BEGIN
 IF (NOT EXISTS(SELECT ID FROM MyTable WHERE ID = OLD.PARENT_ID) THEN
 UPDATE MyTable SET HAS_CHILDREN = 0;
 UPDATE MyTable SET HAS_CHILDREN = 1;
END

Можно, конечно, обойтись и без триггеров и без поля HAS_CHILDREN, сделав такой запрос к базе, который вернет признак наличия потомков у объектов данного уровня. Но моя практика показывает, что удобнее все же иметь такое поле. Это упрощает жизнь и в других ситуациях.

Кайф этого подхода (каждый раз перезапрашивать ветвь) в том, что дерево легко пересвечивать после вставки в него нового пункта. Достаточно вызвать Collapse и Expand родительской ветви.

А вообще я сохраняю в базе данных (для каждого юзера) степень раскрытости его папок просто в виде строки ID, разделенных запятой. При отображении дерева в первый раз я считываю эту строку из базы и просто отыскиваю последовательно Node-ы, у которых в Data лежит следующий ID - затем вызываю Expand для этого Node-а. А при закрытии формы сканирую дерево и формирую строку из ID для тех Nodes[i], которые сейчас распахнуты (HasChildren = True). И сохраняю эту строку в базе данных.

Этот подход мне представляется наилучшим.
Код настолько прост, что мне даже не требовалось его оформлять в компонент. Всего два обработчика событий. И парочка функций.


 
kaif ©   (2006-06-07 21:53) [24]

Извиняюсь, все напутал в текстах триггеров:

В триггере AFTER DELETE делаю:
IF (NOT EXISTS(SELECT ID FROM MyTable WHERE PARENT_ID = OLD.PARENT_ID) THEN
UPDATE MyTable SET HAS_CHILDREN = 0 WHERE ID = OLD.PARENT_ID;

В триггере AFTER INSERT делаю:
UPDATE MyTable SET HAS_CHILDREN = 1  WHERE ID = NEW.PARENT_ID;

В триггере AFTER UPDATE делаю и то и другое вместе:
IF (OLD.PARENT_ID <> NEW.PARENT_ID) THEN
BEGIN
IF (NOT EXISTS(SELECT ID FROM MyTable WHERE ID = OLD.PARENT_ID) THEN
UPDATE MyTable SET HAS_CHILDREN = 0 WHERE ID = OLD.PARENT_ID;
UPDATE MyTable SET HAS_CHILDREN = 1 WHERE ID = NEW.PARENT_ID;
END


 
Сергей М. ©   (2006-06-08 16:05) [25]


> kaif ©   (07.06.06 21:53) [24]


При всем к тебе, Ашот, уважении не кажется ли тебе, что ты (с твоим-то опытом !) мог бы объяснить Авторпу, что "вывод базы данных в виде дерева" - это нонсенс ?


 
Ega23 ©   (2006-06-08 16:24) [26]


> Я обычно делаю дерево так:
> Беру обычный TTreeView.
> На событие OnCollapse удаляю все дочерние Nodes текущего
> Node.
> На событие OnExpand создаю дочерние Nodes одним уровнем
> ниже для распахиваемого пункта, обращаясь всякий раз SQL-
> запросом к базе данных.


Это всё, конечно, замечательно. Но только в том случае, когда не нужно дерево с другими DB-контролами синхронизировать.
А у меня задача - есть один набор данных. Есть DBGrid, в котором отражены некоторые поля этого НД. Есть дерево, где все записи этого НД выведены в виде иерархической структуры. И есть картинка, на которой эти объекты изображены.
Ткнулся на запись в гриде - выбрался соответствующий узел в дереве - подсветилась соответствующая картинка на графике.
Сделал принудительный Locate НД "извне" - во всех трёх контролах установились правлиьные текущие объекты.
Выбрал картинку на графике - всё то же самое.
Самое "западло" в этой ситуации - что компановка программы может быть разная. Может быть только дерево. Или только графика. Или только грид. Или и графика и дерево. И т.д.


 
Сергей М. ©   (2006-06-08 16:58) [27]


> Ega23 ©   (08.06.06 16:24) [26]


При всем при том ты так и не сподобился объяснить, как ты умудряешься вывести "в виде дерева" именно базу данных, а не некий НД)

Про "Не ври" может возьмешь слова обратно ?


 
Ega23 ©   (2006-06-08 17:35) [28]


> При всем при том ты так и не сподобился объяснить, как ты
> умудряешься вывести "в виде дерева" именно базу данных,
> а не некий НД)
>


Ну конечно НД, а не "базу данных". Хотя если сильно постараться, то можно написать запрос, который выведет ПОЛНОЕ содержимое БД в один НД.


> Про "Не ври" может возьмешь слова обратно ?


Если тебя это успокоит, то пожалуйста - беру свои слова обратно.


 
rar ©   (2006-06-08 21:14) [29]

Что то я не совсем понял триггеры.
Поле HAS_CHILDREN что имеет только значения 0 и 1 что ли

Я делаю по другому, прибавляю или удаляю единицу и в этом поле храниться количество дочерних элементов

Правда пришлось это делать без триггеров.

С ними ругается что таблица находиться в изменении у меня СУБД ORACLE


 
atruhin ©   (2006-06-08 21:23) [30]


> Правда пришлось это делать без триггеров.

Вот это плохо. Раньше или позже грабли будут точно. Если в таблицах не более нескольких тысяч записей можно не хранить кол-во, а просто динамически запрашивать.


 
rar ©   (2006-06-09 18:51) [31]


> Вот это плохо. Раньше или позже грабли будут точно. Если
> в таблицах не более нескольких тысяч записей можно не хранить
> кол-во, а просто динамически запрашивать.
> <Цитата>

Если динамически делать запрос, тогда вообще зачем это поле :-))

Оно и предназначено для рисования "плюсика" в TreeView



Страницы: 1 вся ветка

Текущий архив: 2006.08.13;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.038 c
6-1143620055
Std
2006-03-29 12:14
2006.08.13
Определение IP


15-1153301533
cosinus
2006-07-19 13:32
2006.08.13
Эээ... Туплю? Проблеммы с установкой DSPack.


15-1153304180
cosinus
2006-07-19 14:16
2006.08.13
Создание "спутникообразного" меню... Вопросы.


15-1153145240
PSPF2003
2006-07-17 18:07
2006.08.13
Название фильма.


2-1153839112
WolfRamm
2006-07-25 18:51
2006.08.13
Zeos