Как смоделировать взаимоисключающие отношения в SQL Server - PullRequest
5 голосов
/ 24 апреля 2010

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

У меня есть таблица Предметов, с которой можно связать любое количество таблиц, и эти таблицы могут со временем увеличиваться. Элемент может быть связан только с одной другой таблицей, но запись в другой таблице может иметь много связанных элементов.

Примеры таблиц / сущностей, с которыми связаны ссылки: Person, Vehicle, Building, Office. Это все отдельные таблицы.

Пример элементов: Pen, Stapler, Cushion, Tyre, A4 Paper, Plastic Bag, Poster, Decoration"

Например, Poster может быть присвоено Person или Office или Building. В будущем, если они добавят таблицу Conference Room, она также может быть добавлена ​​к этому.

Мои жизненные мысли:

Item
{
  ID,
  Name
}

LinkedItem
{
  ItemID,
  LinkedToTableName,
  LinkedToID
}

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

Я не слишком доволен этим решением, но я не могу думать ни о чем другом. Пожалуйста помоги! :)

Спасибо!

Ответы [ 3 ]

12 голосов
/ 24 апреля 2010

Не рекомендуется хранить имена таблиц в качестве значений столбцов. Это плохой взлом.

Есть два стандартных способа сделать то, что вы пытаетесь сделать. Первый называется наследование одной таблицы . Это легко понять с помощью инструментов ORM, но обойдется без нормализации. Идея состоит в том, что все эти объекты - Person, Vehicle, что угодно - хранятся в одной таблице, часто с несколькими неиспользуемыми столбцами на запись, вместе с полем дискриминатор , который определяет, какой тип сущность.

Поле дискриминатора, как правило, представляет собой целочисленный тип, который сопоставлен с некоторым перечислением в вашем коде. Это также может быть внешний ключ для некоторой таблицы поиска в вашей базе данных, определяющий, какие номера соответствуют каким типам ( не имена таблиц, только описания).

Другой способ сделать это - наследование нескольких таблиц , которое лучше для вашей базы данных, но не так легко отобразить в коде. Вы делаете это, имея базовую таблицу , которая определяет некоторые общие свойства всех объектов - возможно, просто идентификатор и имя - и все ваши "конкретные" таблицы (Person и т. Д.) Используют базу Идентификатор как уникальный внешний ключ (обычно также первичный ключ).

В первом случае исключительность является неявной, поскольку все объекты находятся в одной таблице. Во втором случае существует связь между Item и base ID объекта, что также гарантирует уникальность.

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

Наследование нескольких таблиц ближе к вашей текущей схеме, поэтому я рекомендовал бы пойти на это, если вам не нужно использовать это с Linq to SQL или аналогичным ORM.

Смотрите здесь подробное руководство: Реализация наследования таблиц в SQL Server .

9 голосов
/ 24 апреля 2010

Найдите что-то общее для Персона , Транспортное средство , Здание , Офис . В отсутствие лучшего термина я использовал Entity . Затем реализуйте взаимосвязь супертип / подтип между Entity и его подтипами. Обратите внимание, что EntityID - это PK и FK во всех таблицах подтипов. Теперь вы можете связать таблицу Item с Entity (владелец). В этой модели один элемент может принадлежать только одному объекту ; один объект может иметь (иметь) множество предметов .

model_mutually_exclusive_01

0 голосов
/ 24 апреля 2010

Ваша таблица ссылок в порядке.

проблема в том, что вам нужно будет генерировать динамический sql во время выполнения. Параметризованный sql обычно не позволяет объектам из списка FROM быть параметрами.

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

вы бы инициировали создание этого денормализованного списка при изменении базовой информации, и вы могли бы использовать его для обобщенных запросов, а затем прибегать к своим динамическим запросам, когда это необходимо во время выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...