Дополнительные таблицы или неспецифические внешние ключи?
-
09-06-2019 - |
Вопрос
В системе существует несколько типов объектов, и у каждого есть своя таблица в базе данных.Пользователь должен иметь возможность комментировать любой из них.Как бы вы оформили таблицу (ы) комментариев?Я могу придумать несколько вариантов:
- Одна таблица комментариев со столбцом FK для каждого типа объекта (ObjectAid, ObjectBID и т.д.)
- Несколько таблиц комментариев, по одной для каждого типа объекта (ObjectAComments, ObjectBComments и т.д.)
- Один общий FK (ParentObjectID) с другим столбцом для указания типа ("ObjectA")
Что бы вы выбрали?Есть ли лучший метод, о котором я не думаю?
Решение
@палмси
В значительной степени, но вариация этого шаблона, которую я видел чаще всего, избавляет от ObjectAID
et al. ParentID
становится как PK, так и FK для Parents
.Это дает вам что-то вроде:
Parents
ParentID
ObjectA
ParentID
(FK и PK)ColumnFromA NOT NULL
ObjectB
ParentID
(FK и PK)ColumnFromB NOT NULL
Comments
остался бы прежним.Тогда вам просто нужно ограничить генерацию идентификаторов, чтобы случайно не получить ObjectA
ряд и ObjectB
строка, в которой оба указывают на одно и то же Parents
ряд;самый простой способ сделать это - использовать ту же последовательность (или что угодно еще), которую вы используете для Parents
для ObjectA
и ObjectB
.
Вы также видите множество схем с чем-то вроде:
Parents
ID
SubclassDiscriminator
ColumnFromA (nullable)
ColumnFromB (nullable)
и Comments
останется неизменным.Но теперь вы не можете применить все свои бизнес-ограничения (все свойства подклассов обнуляются) без написания триггеров или выполнения этого на другом уровне.
Другие советы
Можно ли спроектировать схему так, чтобы таблицы с комментариями (из-за отсутствия лучшего слова) следовали одному из стандартных шаблонов моделирования наследования? Если это так, вы можете указать FK таблицы комментариев на общую родительскую таблицу.
@ Хэнк Гей
Так что-то вроде:
- ObjectA
- ObjectAID
- ParentID
- ObjectB
- ObjectBID
- ParentID
- Комментарии
- CommentID
- ParentID
- родители
- ParentID
Будьте осторожны с общими внешними ключами, которые не указывают точно на одну таблицу. Производительность запросов значительно снижается, если вам нужно разделить условие where для типа и указать несколько разных таблиц. Если у вас есть только несколько типов, и число типов не будет расти, то нормально иметь отдельные внешние ключи, допускающие обнуляемость, для разных таблиц, но если у вас будет больше типов, лучше придумать другую модель данных (например, предложение @ palmsey).
Одна из вещей, которые мне нравится делать, - это иметь отдельные таблицы, которые связывают общую таблицу со всеми индивидуальными таблицами.
Итак, для объектов Foo и Bar, а затем комментариев к Foo & Bar у вас будет что-то вроде этого:
- Фу
- Идентификатор Foo (PK)
- Бар
- Идентификатор бара (PK)
- Комментарий
- Идентификатор комментария (PK)
- Текст комментария
- Описание
- Идентификатор Foo (PK FK)
- Идентификатор комментария (PK FK)
- Штрих - код
- Идентификатор бара (PK FK)
- Идентификатор комментария (PK FK)
Эта структура:
- Позволяет вам иметь общую таблицу комментариев
- Не требует базы данных с наследованием таблиц
- Не загрязняет таблицы Foo и Bar информацией, связанной с комментариями
- Позволяет вам прикрепить комментарий к множественный объекты (которые могут быть желаемыми)
- Позволяет вам при желании присоединить другие свойства к соединению Foo / Bar и Comment.
- По-прежнему сохраняет отношения со стандартом (т.е.:быстрые, простые, надежные) внешние ключи