Как смоделировать взаимоисключающие отношения в SQL Server

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

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

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

Пример Объектов Pen, Stapler, Cushion, Tyre, A4 Paper, Plastic Bag, Poster, Decoration"

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

Мои intital мысли:

Item
{
  ID,
  Name
}

LinkedItem
{
  ItemID,
  LinkedToTableName,
  LinkedToID
}

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

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

Спасибо!

6
задан marc_s 25 April 2010 в 08:48
поделиться

3 ответа

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

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

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

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

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

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

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

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

12
ответ дан 8 December 2019 в 05:53
поделиться

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

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

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

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

0
ответ дан 8 December 2019 в 05:53
поделиться

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

model_mutually_exclusive_01

10
ответ дан 8 December 2019 в 05:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: