Дизайн базы данных SQL

Я делаю базу данных для программы, в которой я должен моделировать некоторые отношения в семье. пример: X — отец Y , Y — сын X

Итак, у меня есть таблица Members со всей информацией о каждом члене, поэтому я подумал о том, чтобы установить связь многие ко многим между таблицей Members и самой собой, чтобы Member_Member таблица моста будет иметь столбцы "FK_FromID , FK_ToID" в качестве составного ключа (это правильно?) и "FK_RelationType" в качестве внешнего ключа для RelationTypes, которая будет иметь тип отношения «Отец, мать, сын, дочь» и два отношения, идущие как один ко многим из таблицы Members к этим двум внешним ключам.

Моя проблема: при удалении, если я выберу каскадирование, я создам циклы, потому что, если я удалю члена, будет два прохода удаления для связанных записей в Member_Member мосте, зная что в программе всякий раз, когда я вставляю отношение отца, я также вставляю отношение сына в таблицу Member_Member, есть ли способ или обходной путь, чтобы включить каскадирование, чтобы всякий раз, когда я удаляю член, я удалял связанные записи в Member_member независимо от того, записано ли оно в столбце внешнего ключа "Кому" или "От кого"

Так что я не знаю, что делать, это правильный дизайн в первую очередь или что? , что мне делать с ездой на велосипеде, а также что, по вашему мнению, лучший дизайн для той же проблемы должен знать, что мне нужно указать, какие отношения между двумя сторонами

Большое спасибо за любую помощь и извините за плохой английский Бишой


person Bashawy    schedule 02.03.2010    source источник


Ответы (2)


SQL не очень хорошо справляется с такими «сетевыми» проблемами.

Таблица моста член-член — ужасное название. Это мост «член-родитель» (или «родитель-потомок»). Таблицы мостов не должны иметь "составного ключа". Таблицы моста имеют суррогатный ключ (просто порядковый номер) и пару ссылок FK на другие таблицы. Два FK должны иметь такие имена, как «член» и «родитель», чтобы было совершенно ясно, какова связь в этой таблице.

У каждого есть родитель. Не у всех есть дети. У некоторых родителей нет родителей в этой базе данных; они «лучшие родители».

Проще всего, если у верхних родителей есть строки в родительско-дочернем мосту с родительским FK равным NULL. Таким образом, вы избегаете сверхсложных внешних соединений — у каждого члена есть по крайней мере одна строка член-родитель; в идеале два.

Вы обнаружите много «циклических» проблем, поскольку отношения транзитивны.

Обратите внимание, что вы не можете — в одном стандартном SQL-запросе — найти всех членов семьи, или всех родителей вплоть до вершины семьи, или всех детей и внуков. Есть расширения SQL, которые делают это возможным, но стандарт плохо справляется с этим.

Каскадное удаление не работает, потому что отношения в семье имеют два направления (от родителей к детям, от детей к родителям), но SQL имеет только одно направление (ссылка FK).

Вы можете попытаться гарантировать, что каждый член ДОЛЖЕН иметь хотя бы одну (и не более двух) строк в «member-parent» и удаление члена удаляет две строки в «member-parent» < strong>и ключи имеют правильные имена, вы можете сделать часть этой работы.

Обратите внимание, что когда вы удаляете участника, это нарушает его родительские отношения. Вы удаляете строку член-родитель. Это хорошо. Что насчет их детей? Другие строки, в которых элемент-родитель ссылается на этот удаленный родитель, теперь разорваны. Что это значит? То, что должно быть сделано?

Нет стандартного ответа. Удаление строк из связного графа оставляет элементы несвязанными. Вы должны выработать некоторые разумные правила для этого.

Так как SQL не справляется с этой задачей, проблемы будут возникать во всех проектах.

person S.Lott    schedule 02.03.2010
comment
+1, потому что я согласен с большей частью этого. Я не согласен с тем, что Bridge-таблицы не должны иметь составной ключ. Замещающий первичный ключ необходим, только если связующая таблица имеет собственные атрибуты или на нее ссылаются внешние ключи. И даже в этом случае составной ключ должен применяться как уникальный ключ. - person APC; 02.03.2010
comment
@APC: Если вы когда-нибудь собираетесь использовать ORM, вам понадобятся суррогатные ключи. Как только вы сделаете этот шаг, составные ключи станут ненужным усложнением. Просто создайте индекс производительности и покончите с этим. - person S.Lott; 02.03.2010
comment
Суррогатные ключи не обеспечивают реляционную целостность. Это полезные устройства, но мы по-прежнему должны применять бизнес-ключи, будь то один столбец или несколько столбцов. Теперь многие люди довольны идеей приложения, обеспечивающего целостность данных, но я не один из них. Кроме того, спрашивающий спрашивал о дизайне базы данных, а не об ORM, поэтому я думаю, что мое наблюдение остается в силе. - person APC; 02.03.2010
comment
@APC: суррогатные ключи не обеспечивают целостность? Действительно? Почему нет? Что такое бизнес-ключ? Часть данных, которая может измениться из-за неправильного написания, что, в свою очередь, вызовет каскад изменений? - person S.Lott; 02.03.2010
comment
Я не могу отделаться от ощущения, что это выходит за рамки ветки комментариев. Так или иначе. Суррогатный ключ — это бессмысленный идентификатор; бизнес-ключ — это идентификатор чего-то уникального в реальном мире. Но вы правы, бизнес-ключи могут меняться, поэтому суррогатные ключи полезны. Чугунный пример: адреса электронной почты уникальны, но пользователи захотят изменить адрес, связанный с их учетной записью. Итак, чтобы избежать этого каскадирования (и других осложнений), у нас есть суррогатный идентификатор пользователя (номер). Но мы по-прежнему хотим обеспечить уникальность электронной почты в таблице учетных записей. Не мы??? - person APC; 02.03.2010
comment
@APC: уникальность отличается от формального ключа. Это можно сделать с помощью уникального индекса. Моя точка зрения по-прежнему заключается в том, что слишком много вещей называют ключами, и это приводит к проблемам. Первое место у ORM. Другие места также проявляются как проблемы. Мой универсальный совет — придерживайтесь суррогатных ключей, а для вещей, которые должны быть уникальными, добавляйте уникальный индекс. Суррогатные ключи проще и сложнее взломать. Составные ключи почти всегда плохая идея; лучше использовать простой уникальный индекс для пары полей. - person S.Lott; 02.03.2010
comment
Хорошо, спасибо за всю помощь, я буду использовать Entity framework в качестве ORM, но я не могу понять, почему составной ключ усложнит это? . Кроме того, если мне нужна семейная запись, я могу поместить некоторый внешний ключ в таблицу моста в новое семейство таблиц, а затем я могу получить все семейство в одном выражении SQL (это правильно?). и о гарантии того, что, когда я удаляю родителя, я также удаляю дочерний элемент, могу ли я создать триггер для поиска всех его записей, где он является дочерним, и также удалить его из таблицы моста? Извините за слишком много вопросов - person Bashawy; 03.03.2010
comment
@Bashawy: составной ключ является более сложным, чем суррогатный ключ. Семейный рекорд? Транзитивная выборка всех детей одного родителя? Да, вы можете заставить бридж-таблицу делать это. Да, вы можете добавлять сложные триггеры для реализации любых правил, которые вы создаете. - person S.Lott; 03.03.2010

  1. Предполагая, что у каждого члена может быть только одна мать и один отец, вы сможете вывести все отношения, просто сохранив поля mother_id и father_id в таблице members.

    Однако это сработает только в том случае, если в вашей базе данных не будет недостающей информации. Например, если член X является братом члена Y, узнать это невозможно, если в базе данных не хранятся родители X и Y.

    Если в вашей базе данных не будет отсутствующей информации, описанное выше может упростить управление целостностью данных. Однако запросы могут стать немного сложными.

  2. Мост member_member, который вы предложили, имеет одну серьезную проблему, поскольку он подразумевает направление отношения, так что, если X является отцом Y, Y также является сыном X. Вы предложили определить отношение дважды в обоих направлениях, но в целом это не рекомендуется. Это форма дублирования данных, и вам может быть сложно обеспечить ссылочную целостность при дублировании данных. Помните, что СУБД не знает, что X является отцом Y, это то же самое, что Y является сыном X.

Я знаю, что это не полный ответ, а всего лишь несколько наблюдений. Я полностью согласен с ответом S.Lott, так как не существует стандартного способа "решить " это с реляционными базами данных.

person Daniel Vassallo    schedule 02.03.2010
comment
Большое спасибо за ваш ответ, очень ценю это - person Bashawy; 04.03.2010