powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Вопрос по структуре БД
25 сообщений из 28, страница 1 из 2
Вопрос по структуре БД
    #33173669
StasL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Есть 3 таблицы
Tabl1
-------
ID_Tabl1
Name

Tabl2
------
ID_Tabl2
Name
ID_Tabl1 && для связи с Tabl1 "один-ко-многим"

Tabl3
-------
ID_Tabl3
Name
ID_Tabl2 && для связи с Tabl2 "один-ко-многим"

Проблема в том, что не все записи в Tabl3 будут иметь связь с Tabl2. Эти записи должны иметь связь с Tabl1 напрямую.
Как правильно решить эту задачу? Вводить в Tabl3 ID_Tabl1 и использовать ID_Tabl2 = 0, мне кажется не очень правильно.
Может кто сталкивался с такой задачей?
Заранее благодарен за ответы.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33173697
w3d
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StasL Вводить в Tabl3 ID_Tabl1 и использовать ID_Tabl2 = 0, мне кажется не очень правильно.
Может кто сталкивался с такой задачей?
Заранее благодарен за ответы.
Мне кажется, это будет оптимальный вариант.
Или пересматривать связи в базах.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33174418
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Слишком мало информации.

В твоем описанни непонятно, почему, если запись таблицы 3 напрямую связана с записью таблицы 1 она, тем не менее, физически находится в таблице 3, а не оказалась в таблице 2 (как вроде бы должно).

Почему нельзя ввести, например, 4 таблицу для таких "особенных" записей.

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

В общем, вариантов решения очень много, но нужно более предметно знать, зачем это все нужно.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33174778
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В некоторых случаях (и нередко) стоит отказываться от создания в таблице собственного простого суррогатного первичного ключа, за повсеместное применение которого агитирует в своей статье про таблицы ВладимирМ.
И делать вместо такового составной PK, одна или более частей которого (полей или их сочетаний, входящих в который) являются внешними ключами, ссылающимися на другие таблицы.
В реляционной теории, где-то в том ее разделе, где рассматриваются аспекты нормализации, кажется, подо все это подведена серьезная теоретическая основа, из которой следует, когда нужно поступать только так (иначе непременно возникнут аномалии), а когда можно и не поступать. На эту тему шли довольно серьезные дебаты в форуме "Проектирование БД", и неоднократно. Советую поискать, кому интересно.
Что касается меня, то я обычно при проектировании БД руководствуюсь больше собственным здравым [? ;-)] смыслом, чем теоретическими выкладками. И где-то уже признавался, что порой (когда нахожу достаточным практически) нормализую данные только до второй НФ. ;-)
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33174822
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi Urri!

1) Денормализация - это ОЧЕНЬ сложный о ответственный шаг - лишь имея за
плечами неслабый опыт (и отчётливо понимая все последствия и ЗАРАНЕЕ зная
какими способами они будут устранятся) можно идти на это.
2) Насчёт суррогатного ключа - его использование никак не мешает - твой
"составной" ключ можно оставить кандидатом. Просто в большинстве случаев
обновления таблицы (используя НЕ позаписные xBase команды) проще и
эффективнее осуществлять исходя из простого суррогатного ключа, нежели из
агрегата. Ну и классический вопрос - сегодня ты думаешь что никто и никогда
не станет делать связей с твоей таблицей, а завтра окажется что есть задачи,
навешивающиеся ИМЕННО на PK этой таблицы (банальный аудит, не говоря уже о
какой-то там репликации :) ) - и тут то и начинают сказываться неудобства
проектного решения с составным PK... Я тоже раньше думал что для таблиц
"раскрывающих" связи типа много-ко-многим лучше всего использовать как PK
комбинацию FK от обеих сторон - но сегодня я думаю что проще и безопаснее и
сюда ввести суррогатный PK :)

Posted via ActualForum NNTP Server 1.2
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33176203
StasL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМСлишком мало информации.

В общем, вариантов решения очень много, но нужно более предметно знать, зачем это все нужно.
Tabl1 - это таблица банков
Каждый банк может иметь региональное подразделение, их список в таблице Tabl2.
В состав региональных подразделений входят доп. офисы -- Tabl3
Но существуют банки которые не имеют региональных подразделений, только доп.офисы.
Для тех и других банков описание доп. офисов одинаково, поэтому они находяться в одной таблице Tabl3, за исключением привязки (одни напрямую к банкам, а другие через региональные подразделения).
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33176256
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Как вариант, сделать для конторы существование хотя бы одного отделения обязательным. Уравнять центральные, региональные и доп. офисы в правах (поместить их в одну таблицу, так, чтобы и те и другие, и третьи являлись отделениями одной конторы, ну и разрешить региональным отделениям ссылаться на центральные (т.е. относиться к ним), а доп.офисам - на региональные и/или центральные - чтобы отразить иерархию контор).
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33176448
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то, просто напрашивается решение с древовидной стркутурой.

Т.е. отдельная таблица оффисов (Table3) и отдельная таблица собственно банков (Table1+Table2) с внутренней иерархией.

Дело в том, что ты рассматриваешь "линейную" схему, когда один банк может иметь только и исключительно региональные отделения и не может быть более мелкого (или крупного) дробления. Например, областные отделения внутри региона. Сбербанк, если не ошибаюсь, имеет кучу отделений в одной только Москве.

Кроме того, а чем региональное отделение отличается от собственно банка? В смысле списка реквизитов (полей). Если опустить вопрос "подчиненности" (иерархии), то, как мне кажется, ничем.

Как мне кажется, все-таки более логично объединить банки и их подразделения в одну таблицу.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33176634
StasL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ВладимирМВообще-то, просто напрашивается решение с древовидной стркутурой.

Интересная мысль, спасибо.
А можно по подробнее об этом. Или ссылочку. Что бы я не задавал глупых вопросов, т.к. в БД я новичек, впрочем как и в VFP.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33177056
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi StasL!

Храни информацию по банкам, отделениям и т.п. так как тебе удобнее (в одной
ли таблице, или в трёх разных) ОДНАКО информацию о "принадлежности" вынеси в
отдельную таблицу древовидной структуры - т.е. nID (первичный ключ,
инкрементное поле), nParentID (ссылка на родителя - т.е. ДРУГОЙ nID этой-же
таблицы, или NULL для самого верхнего уровня) и nObjectID (собственно ссылка
на объект - т.е. на запись о банке, отделении и т.п.)
Таким образом ты получишь полную гибкость - можно будет и >3 уровней делать,
и вообще без уровней работать с объектами...

Posted via ActualForum NNTP Server 1.2
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33177458
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StasL ВладимирМВообще-то, просто напрашивается решение с древовидной стркутурой.

Интересная мысль, спасибо.
А можно по подробнее об этом. Или ссылочку. Что бы я не задавал глупых вопросов, т.к. в БД я новичек, впрочем как и в VFP.
Организация хранения древовидной структуры в базе данных - это личное дело каждого. Нет единого стандарта. Многое зависит от конкретных условий задачи.

Вот например разные варианты хранения древовидной структуры:

http://www.pwr.ru/items/?id=3
http://www.osp.ru/win2000/sql/967.htm
http://sdm.viptop.ru/articles/sqltrees.html
http://rdbms.narod.ru/article/tree/index.html

Лично я в дополнении к "классической" структуре ID, ParentID добавил сквозной порядковый номер элемента по всему дереву nOrder.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33177485
StasL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Огромное спасибо всем за участие. Сейчас попробую разобраться.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179208
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi Владимир!

> Лично я в дополнении к "классической" структуре ID, ParentID добавил
> сквозной порядковый номер элемента по всему дереву nOrder.

Не понял, а чем собственно ID не устраивает? Или он у тебя не есть PK и не
есть автоинкрементный?
Я вот добавил бы nRootID - чтобы сразу видеть к какому поддереву принадлежит
элемент - конечно если возможно НЕСКОЛЬКО деревьев (т.е. > 1 элемента имеют
nParentID = .NULL.)

Posted via ActualForum NNTP Server 1.2
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179261
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Igor KorolyovЯ вот добавил бы nRootID - чтобы сразу видеть к какому поддереву принадлежит элемент - конечно если возможно НЕСКОЛЬКО деревьев (т.е. > 1 элемента имеют nParentID = .NULL.)
А я бы, все-таки, банки - parent-таблицу - оставил бы саму по себе, а в отделениях - child-таблице - уже строил бы дерево. Причем ссылку на банк имел в каждом отделении.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179420
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Igor Korolyov
Hi Владимир!

> Лично я в дополнении к "классической" структуре ID, ParentID добавил
> сквозной порядковый номер элемента по всему дереву nOrder.

Не понял, а чем собственно ID не устраивает? Или он у тебя не есть PK и не
есть автоинкрементный?
Я вот добавил бы nRootID - чтобы сразу видеть к какому поддереву принадлежит элемент
Будем в N+1 раз обсуждать преимущества и недостатки разных способов хранения древовидной структуры?

Я, конечно, могу объяснить, зачем это нужно, но стоит ли? Автору вопроса на данный момент требуется принять принципиальное решение будет ли он использовать древовидную структуру или нет. Если будет, тогда и будем обсуждать, как именно это дерево лучше организовать.

PS:

Практически любой способ хранения древовидной структуры - это не нормализованная таблица с дублирующей структурой. Т.е. по сути, всегда есть 2 PK. Один в явном виде как ID, а другой - в скрытом, как фрагмент поля или комбинация полей.

Явный ID используется для внешних связей, а дублирующая структура для оптимизации (ускорения) выборок внутри самого "дерева"
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179429
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UrriА я бы, все-таки, банки - parent-таблицу - оставил бы саму по себе, а в отделениях - child-таблице - уже строил бы дерево. Причем ссылку на банк имел в каждом отделении.
Вы пропустили одно из условий задачи: банк может иметь, а может и НЕ ИМЕТЬ отделений. Собственно, именно этим условием и вызван сам вопрос. Предлагаете вводить фиктивные отделения для таких банков?
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179845
StasL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день всем!
Прочитав информацию по ссылкам, любезно предоставленным Владимиром М, у меня получилась следующая структура:
Код: plaintext
1.
2.
3.
4.
5.
Tabl_Bank                Tabl_RF           Tabl_DO
---------                 --------          --------
ID_Tree                   ID_Tree           ID_Tree
Name                      Name               Name
и т.д                      и т.д               и т.д

Данные о банках, РФ, Доп. офисах мне удобней хранить в разных таблицах, т.к.
помимо Name есть еще некоторые поля различные для каждой таблицы, т.е. "и т.д" для всех таблиц разные
.
И, собственно, таблица дерева
Код: plaintext
1.
2.
3.
4.
Tabl_Tree
--------- 
ID_Tree   && автоинкремент
ID_Parent

Первые три таблицы связаны с Tabl_Tree "один к одному" по полю ID_Tree, которое у них НЕ автоинкремент.
А дальше у меня получается как в старом анекдоте, когда создали самолет с тенисными кортами, бассейнами и т. д., а пилот садясь в кабину говорит: "А теперь попробуем со всей этой фигней взлететь!"

Как мне поддерживать целостность базы? Я так предполагаю что нужно писать свои тригера.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179898
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
StasLКак мне поддерживать целостность базы? Я так предполагаю что нужно писать свои тригера.
В общем, да. Я же уже говорил: дерево - это не стандартная для реляционной базы данных архитектура хранения. Значит просто нет стандартных способов поддержания ее в актуальном состоянии. Придется самому писать все триггера.

Кроме того, автоматически создаваемые триггера в контейнере базы данных FoxPro (Referential Integrity) решают очень частный круг задач. База данных, которая использует только эти триггера достаточно редкий случай. Как правило, все-равно приходится саомостоятельно писать триггера для "не стандартных" (с точки зрения Referential Integrity) правил поддержания ссылочной целостности.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179911
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМ UrriА я бы, все-таки, банки - parent-таблицу - оставил бы саму по себе, а в отделениях - child-таблице - уже строил бы дерево. Причем ссылку на банк имел в каждом отделении.
Вы пропустили одно из условий задачи: банк может иметь, а может и НЕ ИМЕТЬ отделений. Собственно, именно этим условием и вызван сам вопрос. Предлагаете вводить фиктивные отделения для таких банков?Ну дык, в моей реализации банк тоже может не иметь отделений. Правда, пока отделений нет, работать с банком нельзя, потому что работать можно только с отделением банка. Ну и что же: если у банка нет отделений, придется завести отделение "главный офис". К слову, если даже отделения есть, отделение "главный офис" все равно надо завести (иначе от чего строить дерево). По-моему, вполне логичная структура получается. ;-)
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33179926
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PS: А вообще, так ли уж нужна древовидная структура? Вполне возможно, что на практике отделения достаточно расположить под банком плоско, не сплетая их в иерархию.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33180041
StasL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А теперь более "философский" вопрос.
StasL
Есть 3 таблицы
Tabl1
-------
ID_Tabl1
Name

Tabl2
------
ID_Tabl2
Name
ID_Tabl1 && для связи с Tabl1 "один-ко-многим"

Tabl3
-------
ID_Tabl3
Name
ID_Tabl2 && для связи с Tabl2 "один-ко-многим"

Вводить в Tabl3 ID_Tabl1 и использовать ID_Tabl2 = 0.
и
StasL
Код: plaintext
1.
2.
3.
4.
5.
Tabl_Bank                Tabl_RF           Tabl_DO
---------                 --------          --------
ID_Tree                   ID_Tree           ID_Tree
Name                      Name               Name
и т.д                      и т.д               и т.д
И, собственно, таблица дерева
Код: plaintext
1.
2.
3.
4.
Tabl_Tree
--------- 
ID_Tree   && автоинкремент
ID_Parent

Первые три таблицы связаны с Tabl_Tree "один к одному" по полю ID_Tree, которое у них НЕ автоинкремент.

Не могли бы вы вкратце описать "плюсы - минусы" этих структур?
Из-за отсутствия опыта всех "подводных камней" я не вижу.
Заранее благодарен.
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33180100
Urri
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А если так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 Bank              Division 
+--------+      +----------+
| BankID   |-+    | DivisionID |--+
+--------+  \   +----------+  |
|Name    |   \  |Name      |  |
|Other...|    +E| BankID     |  |
+--------+      | ParentID   |Э-+
                |Other...  |
                +----------+
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33180130
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Первый вариант - это по сути 2 типа связи:

Tab1 - Tab2 - Tab3
И
Tab1 - Tab3

Т.е. в данном случае имеем 2 паралельные связи между Tab1 и Tab3 существующие одновременно . Это огромный недостаток. Рано или поздно, но ты получишь конфликт этих связей. Сопровождение и отображение подобной структуры требует дополнительных усилий

Кроме того, FoxPro не позволяет создавать в контейнере базы данных дублирующие постоянные связи между двумя таблицами. Т.е. создать стандартные триггеры через Referential Integrity не получиться. Впрочем, то же самое можно сказать и про древовидную структуру.

Из достоинств - простота структуры. Если в случае наличия записи в Tab2 код записи из Tab1 в Tab3 будет принимать нулевое значение, то получение выборок будет также достаточно простым.

Второй вариант в таком виде прост в реализации и сопровождении, но вот получение любой выборки по такой структуре будет практически невозможно!

Попробуй прикинуть как по этой структуре сделать полный отчет: все банки - все подразделения - все оффисы? В той иерархии, в какой они физически есть. Сразу поймешь, чем вызвано такое разнообразие структур хранения "дерева".
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33181513
Igor Korolyov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Hi Владимир!

> Второй вариант в таком виде прост в реализации и сопровождении, но вот получение любой выборки по такой структуре будет практически невозможно!

Скажем по иному - сделать SQL запрос по такой структуре довольно сложно - придётся либо использовать UDF, либо "подразумевать" разного рода ограничения (типа имеется максимум 3 уровня вложенности, отделение не может находится "под" филиалом и т.п.) и использовать самообъединения.
Хотя если использовать ХП создающие курсоры через внутренние циклы, то "стандартные" задачи решаются достаточно просто.

P.S. И всё-же я не очень понял про твой вариант структуры. Я имел в виду нечто подобное схеме описанной тут http://forum.foxclub.ru/read.php?f=29&i=13406&t=13378 - может быть и ты про что-то подобное говоришь, а я не догоняю? Ибо в ней я не вижу места (необходимости) дополнительному полю-нумератору, и так связь с "основной" таблицей идёт не по полю PK.

Posted via ActualForum NNTP Server 1.2
...
Рейтинг: 0 / 0
Вопрос по структуре БД
    #33181650
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Igor Korolyov
Hi Владимир!
P.S. И всё-же я не очень понял про твой вариант структуры.
Тогда с самого начала. Я храню древовидный справочник в такой структуре

ID - код записи
ParentID - ссылка на родителя
nOrder - сковзной порядковый номер узла в дереве

Чтобы было понятно, что такое nOrder представь себе полностью раскрытое "дерево". Нет ни одного "свернутого" узла. Все узлы дерева видны в списке. Вот в таком, полностью развернутом дереве я и нумерую узлы в порядке их логического следования.

Код: plaintext
1.
2.
3.
4.
5.
6.
nOrder
1	Один
2	|-------Два
3	|	|-------Три
4	|-------Четыре
5	Пять

Т.е. nOrder - Это ни в коем случае не ID (или PK) узла. Это, так сказать, "индекс", определяющий "порядок следования" узлов по вертикали друг за другом.

Что это дает?

Я получаю фиксированный порядок следования узлов в пределах одной ветки. И этот порядок может отличаться как от алфавитного, так и от физического (по мере добавления записей).


Выстроив узлы в порядке возрастания nOrder я элементарно получаю возможность "вырезать" нужный фрагмент дерева со всеми подчиненными узлами. Это делается в 3 запроса.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
LOCAL lnID, lnParentID, lnOrderMin, lnOrderMax
lnID = (код узла)

* Определяю ссылку на родителя узла, для которого ищем все подчиненные узлы
* А также порядковый номер этого узла
SELECT ParentID, nOrder FROM MyTab INTO CURSOR curOne WHERE ID = m.lnID 
lnParentID = curOne.ParentID
lnOrderMin = curOne.nOrder

* Теперь нахожу первый "по порядку следования" узел, имеющий того же родителя. 
* Точнее, нахожу его "порядковый номер"

SELECT TOP  1  nOrder FROM MyTab INTO CURSOR curOne ;
WHERE ParentID = m.lnParentID AND nOrder > m.lnOrderMin ;
ORDER BY nOrder

lnOrderMax = curOne.nOrder

* Все, что находится в диапазоне от lnOrderMin до lnOrderMax - это и есть дочернии узлы указанного узла.

SELECT * FROM MyTab WHERE nOrder BETWEEN m.lnOrderMin AND m.lnOrderMax

Разумеется, тут надо учесть возможность того, что у указанного узла нет "братьев". Но это уже детали.

Т.е. nOrder позволяет, кроме позиционирования узлов существенно облегчить получение нужных выборок. Все выборки сводятся к определению граничных порядковых номеров (nOrder) и последующей итоговой выборке. Т.е. максимум в 3 запроса я могу получить практически любую нужную информацию. Ну, почти

Недостатком всего этого является необходимость написание относительно сложных триггеров, для поддержания целостности nOrder. Операции вставки или перемещения узла приводят к необходимости модификации, в среднем, половины таблицы (сдвиг значений nOrder у записей лежащих "после" вставляемой)

Впрочем, необходимость написания сложных триггеров возникает при любом отступлении от классической схемы ID, ParentID.
...
Рейтинг: 0 / 0
25 сообщений из 28, страница 1 из 2
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Вопрос по структуре БД
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]