Я редко сталкиваюсь с ситуацией, когда одна таблица для нескольких типов сущностей кажется лучше, чем одна таблица для каждого типа сущности. Вот пример, который имеет смысл для меня, но академически он кажется неправильным.
ВОПРОС: Могу ли я сделать это и при этом иметь «звуковую» архитектуру?
Пример следует
Предположим, два типа сущностей, корпорация и личность. Корпорация обычно принадлежит одному человеку, но иногда другая корпорация владеет корпорацией.
Удерживая эту мысль и добавляя к ней, скажем, к каждой корпорации прикреплен зарегистрированный агент, который отвечает за юридическое создание корпорации. Следуя моей иллюстрации, зарегистрированным агентом может быть либо физическое лицо, либо корпорация.
Если вы считаете, что владельцем [родителем] корпорации [ребенка] может быть либо физическое лицо, либо корпорация, вы можете начать видеть проблему в сохранении третьей нормальной формы и во избежание избыточности.
В отличие от моего примера, если бы только люди могли владеть корпорациями, таблица ссылок на владение очень условна и имеет столбцы: OwnershipID (вроде ненужный), CorporationID, PersonID.
Вместо этого вам нужно что-то вроде: OwnershipID, CorporationID, OwnerID, OwnerEntityType (корпоративное или физическое лицо). Не поймите меня неправильно, вы можете сделать эту работу, но это будет не очень весело, если не сказать больше.
Продолжая приведенный мной пример, вам нужно назначить агента для каждой корпорации. Обычно агент является одним из владельцев (человек). В этом случае вы действительно хотите вернуться к одной записи этого человека. Вы не хотите записывать человека как владельца, а затем как агента (в таблице агентов). Это было бы излишним.
Подобно этой «проблеме», зарегистрированный агент также может быть корпорацией, такой как юридическая фирма, CPA или коммерческая компания, чтобы назвать некоторые типичные примеры. Точно так же, как агент-агент, корпорация-агент действительно не должна получать свою собственную запись как агент-субъект. Вместо этого он должен вернуться к своему корпоративному существованию в таблице Корпорации. [за исключением того, что я в конечном итоге говорю, что у вас нет таблицы CorporationEntity]
Точно так же, как таблица ссылок, которая сопоставляет каждую корпорацию с ее владельцем (ами) любого типа, лицом или корпорацией, у вас может быть таблица ссылок агента: AgentRepresentationID, CorporationID, AgentID, AgentType ... но, опять же, это будет будьте уродливы (IMO), когда вам нужно собрать вместе связанных агентов - некоторые из таблицы Person, некоторые из таблицы Corporation.
Вот почему я говорю, что в подобных случаях вы можете видеть, как нейтральный тип сущности может быть выгодным. Было бы что-то вроде этого:
Таблица: EntityAll
Ключевые столбцы: EntityID, EntityType (или EntityTypeID, если вы настаиваете, укажите ссылку, чтобы получить описание), EntityName (существуют проблемы с именами и различными типами ... не по теме в этом посте)
Таблица ссылок: Корпоративное владение
Ключевые столбцы: OwnershipID (опять же, мой комментарий о том, что это как-то не нужно), ChildEntityID (принадлежащий объект; для ясности назван «Дочерний», я бы не назвал это так) ParentEntityID (родительский объект)
Таблица ссылок: AgentRepresentation
Ключевые столбцы: AgentRepresentationID (... я не скажу), CorporationEntityID (представляемая сущность корпорации), AgentEntityID (из таблицы Entity, приравнивая к записи, которая является агентом здесь)
Хотя вы можете быть в порядке с моей архитектурой, вы должны быть немного обеспокоены именами столбцов в таблицах ссылок. Это не дает мне покоя. Обычно имена второго и третьего столбцов в этих таблицах точно совпадают с именами столбцов, к которым вы ПРИСОЕДИНЯЕТЕСЬ в соответствующей таблице каждого объекта (ха-ха, но у каждого объекта нет соответствующей таблицы, поэтому вы не можете иметь имена столбцов таблицы ссылок, соответствующие имена столбцов источника, потому что они являются одним и тем же столбцом). Технически это не имеет значения, но это нарушит ваши соглашения об именах, которые имеют значение, но не настолько, чтобы этого не делать.
В случае, если я еще недостаточно хорошо отвез его домой, вот как вы соберете его. Вы присоединяетесь к таблице EntityAll самостоятельно, чтобы получить то, что вам нужно.
Список всех корпусов и их владельцев (в T-SQL):
SELECT Corp.EntityName as CorpName, Owner.EntityName as OwnerName
FROM EntityAll as Corp
JOIN CorporationOwnership as Link on (Corp.EntityID = Link.ChildEntityID)
JOIN EntityAll as Owner on (Link.ParentEntityID = Owner.EntityID)
Следовательно, вы бы сделали то же самое, чтобы вернуть агента вместо владельца (ов).
Я понимаю, что это не то, как мы обучаемся создавать таблицы, но я твердо убежден, что мое решение исключает избыточные данные и облегчает кодирование, управление и чтение.
P.S. Я недавно предоставил этот пример в качестве ответа на старый вопрос о SO. Будучи старым вопросом, не было никакого диалога. Мне нужно реализовать этот самый пример, и мне любопытно, каковы будут последствия этой архитектуры.
Вот предыдущий вопрос / ответ:
Хороший дизайн таблицы базы данных: одна таблица, смешивающая разные сущности или отдельная таблица для каждой сущности