Ваш случай выглядит как пример шаблона проектирования, известного как «Специализация обобщения» или Gen-Spec для краткости.Вопрос о том, как смоделировать gen-spec с использованием таблиц базы данных, постоянно возникает в SO.
Если бы вы моделировали gen-spec в OOPL, таком как Java, вы бы использовали средство наследования подклассов, чтобы позаботитьсяиз деталей для вас.Вы просто определили бы класс, который позаботится об обобщенных объектах, а затем определите коллекцию подклассов, по одному для каждого типа специализированного объекта.Каждый подкласс расширил бы обобщенный класс.Это легко и просто.
К сожалению, реляционная модель данных не имеет встроенного наследования подклассов, и, насколько мне известно, системы баз данных SQL не предоставляют никаких таких возможностей.Но тебе не повезло.Вы можете спроектировать свои таблицы для моделирования gen-spec таким образом, чтобы это соответствовало структуре классов ООП.Затем вам нужно организовать собственный механизм наследования при добавлении новых элементов в обобщенный класс.Подробности приведены ниже.
Структура класса довольно проста: одна таблица для класса gen и одна таблица для каждого подкласса spec.Вот хорошая иллюстрация с сайта Мартина Фаулера. Наследование таблицы классов .Обратите внимание, что на этой диаграмме Cricketer является одновременно подклассом и суперклассом.Вы должны выбрать, какие атрибуты идут в какие таблицы.На диаграмме показан один примерный атрибут в каждой таблице.
Сложность в том, как определить первичные ключи для этих таблиц.Таблица классов gen получает первичный ключ обычным способом (если только эта таблица не является специализацией еще одного обобщения, такого как крикетисты).Большинство дизайнеров дают первичному ключу стандартное имя, например, «Id».Они используют функцию автонумерации для заполнения поля Id.Таблицы классов спецификации получают первичный ключ, который может называться «Id», но функция автонумерации не используется.Вместо этого первичный ключ каждой таблицы подклассов ограничен ссылкой на первичный ключ обобщенной таблицы.Это делает каждый из специализированных первичных ключей как внешним ключом, так и первичным ключом.Обратите внимание, что в случае игроков в крикет поле Id будет ссылаться на поле Id в проигрывателе, а поле Id в Боулерах будет ссылаться на поле Id в игроке в крикет.
Теперь, когда вы добавляете новые элементы, вы должны поддерживать ссылочную целостность, вот как.
Сначала вы вставляете новую строку в таблицу gen, предоставляя данные для всех ее атрибутов, кроме первичного ключа.,Механизм автонумерации генерирует уникальный первичный ключ.Затем вы вставляете новую строку в соответствующую таблицу спецификаций, включая данные для всех ее атрибутов, включая первичный ключ.Используемый вами первичный ключ - это копия только что созданного первичного ключа.Такое распространение первичного ключа можно назвать «наследованием бедняков».
Теперь, когда вам нужны все обобщенные данные вместе со всеми специализированными данными только из одного подкласса, все, что вам нужно сделать, это объединить две таблицыпо общим ключам.Все данные, которые не относятся к рассматриваемому подклассу, будут исключены из объединения.Это гладко, легко и быстро.
Дизайн таблиц SQL, которые реализуют шаблон gen-spec, может быть немного сложным.Учебники по дизайну баз данных часто затмевают эту тему.Но на практике это происходит снова и снова.
Если вы будете искать в Интернете «обобщение специализации реляционное моделирование», вы найдете несколько полезных статей, которые научат вас, как это сделать.Вам также будет несколько раз указано, что эта тема поднималась раньше на этом форуме.
В статьях обычно показывается, как выw разработать единую таблицу для сбора всех обобщенных данных и одну специализированную таблицу для каждого подкласса, которая будет содержать все данные, относящиеся к этому подклассу.Интересная часть включает в себя первичный ключ для таблиц подклассов.Вы не будете использовать функцию автонумерации СУБД для заполнения первичного ключа подкласса.Вместо этого вы запрограммируете приложение на распространение значения первичного ключа, полученного для обобщенной таблицы, в соответствующую таблицу подклассов.
Это создает двустороннюю связь между обобщенными данными и специализированными данными.Простое представление для каждого специализированного подкласса будет собирать обобщенные и специализированные данные вместе.Это легко, когда вы освоите его, и он работает довольно хорошо.