Каков наилучший способ реализовать полиморфную ассоциацию в SQL Server? - PullRequest
53 голосов
/ 09 августа 2011

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

Вот подход с несколькими столбцами

Multiple Column approach

Вот подход без внешнего ключа

No Foreign Key Approach

А вот и подход базовой таблицы

Base table approach

Ответы [ 9 ]

3 голосов
/ 09 августа 2011

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

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

2 голосов
/ 24 мая 2016

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

1 голос
/ 14 июля 2018

Я использовал следующее решение для решения аналогичной проблемы:

Конструкция на основе многих-многих. Несмотря на то, что отношение между объектами N и Something равно 1-многим, оно эквивалентно отношению многих-многих с модификацией PK таблицы отношений.

Сначала я создаю таблицу отношений между ObjectN и Something для Object, а затем использую столбец Something_ID в качестве PK.

Это DDL отношения Something-Object1, который одинаков для Object2 и Object3:

CREATE TABLE Something
(
    ID INT PRIMARY KEY,
    .....
)

CREATE TABLE Object1
(
   ID INT PRIMARY KEY,
   .....
)

CREATE TABLE Something_Object1
(
    Something_ID INT PRIMARY KEY,
    Object1_ID INT NOT NULL,
    ......

    FOREIGN KEY (Something_ID) REFERENCES Something(ID),
    FOREIGN KEY (Object1_ID) REFERENCES Object1(ID)
)

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

0 голосов
/ 05 февраля 2017

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

0 голосов
/ 27 января 2017

Я использовал первый подход. При экстремальных нагрузках стол «Нечто» становится узким местом.

Я применил шаблон DDL для своих разных объектов, при этом специализации атрибутов добавляются в конец определения таблицы.

На уровне БД, если мне действительно нужно представить свои классы как набор записей "Нечто", тогда я ставлю их поверх

SELECT "Something" fields FROM object1
UNION ALL
SELECT "Something" fields FROM object2
UNION ALL
SELECT "Something" fields FROM object3

Задача состоит в том, как назначить не конфликтующий первичный ключ, если у вас есть три независимых объекта. Обычно люди используют UUID / GUID, однако в моем случае ключом было 64-битное целое число, сгенерированное в приложении на основе времени и машины, чтобы избежать конфликтов.

Если вы воспользуетесь этим подходом, то избежите проблемы объекта «Нечто», вызывающего блокировку / блокировку.

Если вы хотите изменить объект «Нечто», то это может быть неудобно, теперь у вас есть три независимых объекта, каждый из которых потребует изменения их структуры.

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

0 голосов
/ 28 июля 2016

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

Мой совет - сделать обзор ожидаемого типа доступа к этим таблицам:

  1. Будете ли вы использовать слой OR, хранимые процедуры или динамический SQL?
  2. Какое количество записей вы ожидаете?
  3. Каков уровень различий между различными подклассами?Сколько столбцов?
  4. Будете ли вы выполнять агрегирование или другие сложные отчеты?
  5. Будет ли у вас хранилище данных для отчетов или нет?
  6. Вам часто нужно будет обрабатывать записи разных подклассов в одном пакете?...

На основании ответов на эти вопросы мы могли бы найти соответствующее решение.

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

0 голосов
/ 04 мая 2016

Подход 1 лучше, но связь между чем-то и object1, object2, object3 должна быть один к одному.

Я имею в виду FK в дочерней (object1, object2, object3) таблице должен быть ненулевым уникальным ключом или первичнымключ для дочерней таблицы.

объект1, объект2, объект3 может иметь значение полиморфного объекта.

0 голосов
/ 28 апреля 2016

Я использовал то, что, я думаю, вы бы назвали подходом к базовым таблицам. Например, у меня были таблицы для имен, адресов и телефонных номеров, каждая из которых была идентифицирована как PK. Затем у меня была основная сущность таблицы сущностей (entityID) и таблица связывания: attribute (entityKey, attributeType, attributeKey), где attributeKey мог указывать на любую из первых трех таблиц, в зависимости от attributeType.

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

Недостатки: довольно сложные запросы для создания простых наборов результатов затрудняли управление (т. Е. У меня были проблемы с наймом людей с достаточно хорошими отборами T-SQL); производительность оптимальна для ОЧЕНЬ конкретных случаев использования, а не для общего; Оптимизация запросов может быть хитрой

Прожив с этой структурой в течение нескольких лет после гораздо более долгой карьеры, я не решался бы использовать ее снова, если у меня не будут те же странные ограничения бизнес-логики и шаблоны доступа. Для общего использования я настоятельно рекомендую, чтобы ваши типизированные таблицы напрямую ссылались на ваши объекты. То есть Entity (entityID), Имя (NameID, EntityID, Name), Телефон (PhoneID, EntityID, Phone), Электронная почта (EmailID, EntityID, Электронная почта). У вас будет некоторое повторение данных и некоторые общие столбцы, но будет гораздо проще программировать и оптимизировать.

0 голосов
/ 10 октября 2015

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

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

...