![]() |
Модераторы: Akella |
![]() ![]() ![]() |
|
FMA |
|
|||
Новичок Профиль Группа: Участник Сообщений: 38 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
Разрабатываю БД на Firebird 2.1.3, для доступа использую компоненты FibPlus.
Используется древовидная структура:
В интерфейсной части программы показывается полученное дерево и данные в виде таб-цы. При перемещении по узлам дерева, показываются данные которые входят конкретно в группу. Суть проблемы состоит в том как лучше организовать обработку показа всех данных, входящих в подгруппы выделенной группы? Одновременно с программой будут работать несколько пользователей. Количество записей будте около 10 тыс. Кто-нибудь сталкивался с такой проблемой? |
|||
|
||||
Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Глубина вложености жестко фиксирована и равна единице? В чем же тогда проблема? 1. Пользователь выбирает узел дерева. 2. Клиентское приложение определяет, какому ID_GRD соответствует этот узел. 3. Клиентское приложение вызывает на сервере зарение подготовленную храниму процедуру, которая делает примерно вот это:
Передавая в качестве входного параметра полученный ранее ID_GRD. 4. Клиентское приложение принимает от сервера данные, которые возвращает хранимая процедура. -------------------- Слава Україні! |
|||
|
||||
FMA |
|
|||
Новичок Профиль Группа: Участник Сообщений: 38 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
Вложенность может быть какой угодно, т.е. у одной группы может быть сколько угодно своих подгрупп, у которых также могут быть подгруппы.
С простой выборкой конкретной группы - проблем нет. Самое интересное, как организовать выборку всех данных из всех подгрупп входящих в выбранную группу. |
|||
|
||||
Gluttton |
|
||||||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
А вот тогда, я не согласен со структурой БД ![]() Если элемент структуры, может выступать в качестве структуры, то я предлагаю вот это:
Заменить на одну таблицу:
И тогда, применив рекурсивный зарос, решаем тривиальную задачу... -------------------- Слава Україні! |
||||||
|
|||||||
FMA |
|
|||
Новичок Профиль Группа: Участник Сообщений: 38 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
Не совсем хорошо, т.к. у группы есть свои параметры, а у данных входящих в нее свои. Большой дубляж данных получится.
Хотя насчет рекурсионного запроса, думаю не проблема будет и для нынешней структуры написать. Насчет отображения пользователю всех данных - не повесит ли он сетку при быстром переходе с одного узла на другой? Понимаю что идет считывание только видимых в таблице строк. Но тут вопрос вот еще в чем - а если пользователь захочет данные отсортировать, да еще и по нескольким столбцам? Как вариант, конечно можно сразу считать все данные, и обойтись простой фильтрацией данных в дальнейшем. Но мне он как-то не нравится. |
|||
|
||||
Gluttton |
|
||||||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
ОК. Тогда так:
Не советчик в практических аспектах :( ... Но в голову приходит следующее... Можно сделать несколько хранимых процедур... Первая - отрабатывает быстро и выбирает первые N записей. Вторая - стартует в отдельном потоке и не зависимо от того потребуются ли пользователю другие данные или нет подгружает их в локальный DataSet... Это могло бы быть оправдоно в том случае, если среднестатистического пользователя в большинстве случаев устраивали бы данные по умолчанию (т.е. результат первого запроса). Трафик от этого не уменьшится, но как бы удобнее... наверное... А можно ещё поток второго запроса периодически усыплять... А если например через какое то время t пользователь не "затребовал" других данных, то поток второго запроса можно убить... Это всё при том, что нет критической необходимости предоставлять пользователю обнавленные данные. А если есть, то всё намного сложнее ![]() ![]() Это так... Пятничные мысли ![]() -------------------- Слава Україні! |
||||||
|
|||||||
Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Я это к тому, что не совсем понятно, как при существующей структуре БД реализовать под-узел? Как узнать является ли данный узел корневым, или вложен в какой-нибудь узел? А сделать это можно добавив поле ID parent, в котором бы хранился ID родительского узла или же 0 для корневых узлов... Ещё раз обращу внимание на то, что при такой реализации составление рекурсивного запроса на обход узла является задачей тривиальной... -------------------- Слава Україні! |
|||
|
||||
jsa |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 704 Регистрация: 19.1.2006 Где: Новосибирск Репутация: 1 Всего: 20 |
FMA, почитай статью, там много интересно описывается, я думаю многие вопросы отпадут сами собой
-------------------- Все мы, на перине с песней, строим небо на земле © Ю. Шевчук |
|||
|
||||
FMA |
|
|||
Новичок Профиль Группа: Участник Сообщений: 38 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
А в таблице дерева TABLE GROUP_DATA у меня есть поле ENTRY, в котором и хранится номер "родителя" данной подгруппы. (Надо было, его попроще обозвать. Извиняюсь). Большое спасибо за ссылочку, статья и вправду полезная. |
|||
|
||||
Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
jsa, не совсем согласен...
Вот тут похожая тема обсуждалась... Nested Sets необходимы там, гне нет возможности испльзовать рекурсию, а в Firebird такая возможность есть... В Nested Sets удобно делать запросы на выборку, но запросы на вставку или изменение очень ресурсоемкие. Так что это альтернатива, но не панацея ![]() -------------------- Слава Україні! |
|||
|
||||
jsa |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 704 Регистрация: 19.1.2006 Где: Новосибирск Репутация: 1 Всего: 20 |
наверное я пропустил эту возможность Gluttton, можно пожалуйста поподробнее, как использовать рекурсию в Firebird не согласен с чем? статья - очередной взгляд на проблему хранения деревьев в sql, я никого не принуждал, использовать способы, описанные в статье, и не говорил что это панацея Добавлено через 1 минуту и 19 секунд дык это и была суть этого топика ![]() -------------------- Все мы, на перине с песней, строим небо на земле © Ю. Шевчук |
|||
|
||||
Deniz |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1251 Регистрация: 16.10.2004 Где: Новый Уренгой Репутация: 22 Всего: 44 |
сам пока не пользуюсь, но ...
Выдержка из этого документа
-------------------- "Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с) |
|||
|
||||
jsa |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 704 Регистрация: 19.1.2006 Где: Новосибирск Репутация: 1 Всего: 20 |
да... действительно пропустил ![]() -------------------- Все мы, на перине с песней, строим небо на земле © Ю. Шевчук |
|||
|
||||
Gluttton |
|
||||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Приведу пример, но позднее... Прошу не обращать внимания ![]() Это я наверное сам с собой ![]()
Согласен. Как бы да, но я не думаю, что топикстартер при работе с БД ограничится только выборкой, хотя это топикстартеру виднее ![]() -------------------- Слава Україні! |
||||
|
|||||
Gluttton |
|
||||||||||||||||||||||||||||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
UPD...
UPD, внес инменения на основании замечаний Deniz по организации каскадного удаления. Deniz, спасибо за поддержку ![]() jsa, как и обещал привожу пример работы с древовидными структурами на Firebird с использованием рекурсивных запросов. Создадим БД, которая описывает файловую систему (очень и очень приблизительно ![]() Создадим две таблицы: таблицу с директориями D и таблицу с файлами F. следующим образом:
Создадим внешние ключи:
Заполним БД тестовыми данными:
Для первичных ключей реализованы соответсвующие генераторы и триггеры для из заполнения автоинкрементными значениями. Получим примерно следующее: Папки: ![]() Файлы: ![]() Реализуем запрос на выборку всех объектов (как папок так и файлов) расположенных в заданой. Создадим хранимую процедуру с рекурсивным запросом, которая принимает один параметр - папка в которой производиться поиск и возвращает две колонки данных, в первой будем отображать имена объектов, а во второй путь к объекту.
Теперь обратимся к БД с запросом:
В результате выполнения запроса получим следующие данные: ![]() Очевидно, что для того, что бы реализовать выбор только каталогов в указаной папке необходимо из хранимой процедуры удалить один из рекурсивных подзапросов:
Для выбора только файлов в указанной папке и ее подпапках, необходимо заменить код рекурсивного запроса на следующий:
Задача вставки данных решается относительно просто. Для этого необходимо создать хранимую процедуру без использования рекурсии, которая будет принимать например имя родительской папки и, не возвращая никаких параметров, создавать в ней папку (задача вставки файлов решается аналогично):
Теперь можно вставлять данные в БД использую следующий запрос:
Выполним вновь запрос на отображение данных Вот примерно, что должно получиться: ![]() Задача удаления папки (и конечно же всего её содержимого) может быть решена несколькими способами. В обоих случаях процедура принимает одно значение - имя папки, которую необходимо удалить и не возвращает значений. Наиболее простой (предложенный Deniz) способ - это использовать ограничения каскадного удаления. Запрос на создание хранимой процедуры может выглядеть так:
Второй способ, более громоздкий и ресурсоёмкий – это без использования ограничений. Я удалил его из поста, дабы не захламлять последний, но оставил в закомментированном виде в скрипте, который присоединен к посту. Он может быть полезен как шаблон для решения задачи удаления только файлов в выбранной папке и её подпапках (для этого необходимо из приведенного запроса удалить первый оператор delete). Выполним следующий запрос:
И вновь проверим содержимое папки 'media':
Должно получиться примерно следующее: ![]() Выполним запрос на отображени папки 'system':
Получиться: ![]() Реализация запросов на обновление данных всех объектов папки аналогична реализации запроса на выборку данных. Запрос на обновления приведен в прилагаемом скрипте. Работает ![]() Вот скрипт по созданию демонстрационной БД. Это сообщение отредактировал(а) Gluttton - 20.10.2009, 10:30 Присоединённый файл ( Кол-во скачиваний: 10 ) ![]() -------------------- Слава Україні! |
||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
jsa |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 704 Регистрация: 19.1.2006 Где: Новосибирск Репутация: 1 Всего: 20 |
Gluttton, отличный пример
![]() -------------------- Все мы, на перине с песней, строим небо на земле © Ю. Шевчук |
|||
|
||||
Deniz |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1251 Регистрация: 16.10.2004 Где: Новый Уренгой Репутация: 22 Всего: 44 |
а зачем так сложно? Создать ссылочную целостность и on delete cascade и файлов и папок. -------------------- "Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с) |
|||
|
||||
Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Спасибо!
Хм... Об этом как то и не подумал... Попробую реализовать удаление с использованием ссылочной целосности. Спасибо за рецензирование ![]() ![]() -------------------- Слава Україні! |
|||
|
||||
jsa |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 704 Регистрация: 19.1.2006 Где: Новосибирск Репутация: 1 Всего: 20 |
вот только будет ли работать delete cascade в рекурсии -------------------- Все мы, на перине с песней, строим небо на земле © Ю. Шевчук |
|||
|
||||
Deniz |
|
|||
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1251 Регистрация: 16.10.2004 Где: Новый Уренгой Репутация: 22 Всего: 44 |
будет, проверено опытом.
Если использовать пример Gluttton, то запрос
-------------------- "Для того чтобы сделать шаг вперед, достаточно пинка сзади" (с) |
|||
|
||||
Gluttton |
|
|||
![]() Начинающий ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1170 Регистрация: 28.8.2008 Где: Феодосия Репутация: 7 Всего: 54 |
Проверил, будет ![]() Deniz, спасибо за подсказку в этой и соседней теме ![]() -------------------- Слава Україні! |
|||
|
||||
FMA |
|
|||
Новичок Профиль Группа: Участник Сообщений: 38 Регистрация: 30.4.2008 Репутация: нет Всего: нет |
Gluttton, спасибо за пример с рекурсией.
И всем остальным тоже Большое спасибо за помощь. |
|||
|
||||
![]() ![]() ![]() |
Правила форума "Interbase" | |
|
Обязательно указание: 1. Версию InterBase (Firebird, Yaffil) 2. Способа доступа (ADO, BDE, IBX и т.д.)
Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella. |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | Firebird, Interbase | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |