Мне нужно смоделировать ситуацию, когда у меня есть таблица Chequing_Account (которая содержит бюджет, номер iban и другие данные счета), которая должна быть связана с двумя разными таблицами Person и Corporation, которые могут иметь 0, 1 или несколько чековых счетов.
Другими словами, у меня есть два отношения «один ко многим» с одной и той же таблицей.
Я хотел бы услышать решения для этой проблемы, которые уважают требования нормализации. Большинство решений, о которых я слышал, это:
1) найти общую сущность, к которой принадлежит и Person, и корпорацию, и создать таблицу связей между этой таблицей и таблицей Chequing_Account, в моем случае это невозможно, и даже если бы я хотел решить общую проблему, а не этот конкретный экземпляр.
2) Создайте две таблицы ссылок PersonToChequingAccount и CorporationToChequingAccount, которые связывают две сущности с проверочными счетами. Однако я не хочу, чтобы два человека имели один и тот же аккаунт для проверки, и я не хочу, чтобы физическое лицо и корпорация имели общий счет для проверки! увидеть это изображение
3) Создайте два внешних ключа в Учетной записи Chequing, которые указывают на Корпорацию и Физическое лицо, однако я бы, таким образом, обеспечил, чтобы Лицо и Компания могли иметь много учетных записей Chequing, однако мне пришлось бы вручную убедиться, что для каждой строки ChequingAccount не оба отношения указывают на Корпорация и Физическое лицо, потому что чековый счет принадлежит корпорации или Физическому лицу. увидеть это изображение
Есть ли другое, более чистое решение этой проблемы?
источник
OwnerTypeID
вChecquingAccount
таблице, с1=Corporation
и2=NaturalPerson
? Таким образом, вам нужен только одинOwnerID
элемент вChecquingAccount
таблице, который вы можете индексировать вместе сOwnerTypeID
.CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)
хотя я предпочитаю решение 1 (но это только я). Это намного "чище".ChecquingAccount
таблице записьOwnerTypeID=1
иOwnerID=123
, указывающую, что это типCorporation
, следовательно, идентификатор123
вCorporation
таблице. OwnerTypeID сообщает вам, какая таблица, а OwnerID сообщает вам идентификатор в этой таблице.Customers
стол.Ответы:
Реляционные базы данных не созданы, чтобы справиться с этой ситуацией идеально. Вы должны решить, что является наиболее важным для вас, а затем сделать свой компромисс. У вас есть несколько целей:
Проблема в том, что некоторые из этих целей конкурируют друг с другом.
Решение для подтипа
Вы можете выбрать решение для подтипа, в котором вы создаете супертип, в который входят как корпорации, так и отдельные лица. Этот супертип, вероятно, будет иметь составной ключ натурального ключа подтипа плюс атрибут разделения (например
customer_type
). Это нормально в том, что касается нормализации, и позволяет вам обеспечивать ссылочную целостность, а также ограничение взаимной исключительности корпораций и отдельных лиц. Проблема в том, что это делает поиск данных более сложным, потому что вы всегда должны переходить в зависимости от того,customer_type
когда вы присоединяете учетную запись к владельцу учетной записи. Это, вероятно, означает использованиеUNION
и наличие большого количества повторяющихся SQL в вашем запросе.Решение с
двумя внешними ключами Вы можете выбрать решение, в котором вы храните два внешних ключа в своей учетной записи: один для корпорации и один для человека. Это решение также позволяет поддерживать ссылочную целостность, нормализацию и взаимную исключительность. Он также имеет тот же недостаток поиска данных, что и решение для подтипа. На самом деле, это решение похоже на решение для подтипа, за исключением того, что вы попадаете на проблему ветвления логики объединения «раньше».
Тем не менее, многие разработчики моделей данных посчитали бы, что это решение уступает решению для подтипа из-за способа применения ограничения взаимной исключительности. В решении для подтипа вы используете ключи для обеспечения взаимной исключительности. В решении с двумя внешними ключами вы используете
CHECK
ограничение. Я знаю некоторых людей, которые имеют необоснованное предубеждение против проверочных ограничений. Эти люди предпочли бы решение, которое сохраняет ограничения в ключах.Решение «денормализованных» атрибутов разделения
Существует еще один вариант, когда вы сохраняете один столбец внешнего ключа в таблице контрольного счета и используете другой столбец, чтобы сообщить вам, как интерпретировать столбец внешнего ключа (RoKa's
OwnerTypeID
колонка). Это по существу исключает таблицу супертипа в решении подтипирования путем денормализации атрибута разделения на дочернюю таблицу. (Обратите внимание, что это не является строго «денормализацией» в соответствии с формальным определением, потому что атрибут разделения является частью первичного ключа.) Это решение кажется довольно простым, поскольку оно позволяет избежать использования дополнительной таблицы для более или менее одинакового действия, и сокращает количество столбцов внешнего ключа до одного. Проблема с этим решением состоит в том, что оно не избегает ветвления логики поиска и, более того, оно не позволяет поддерживать декларативную ссылочную целостность. Базы данных SQL не имеют возможности управлять одним столбцом внешнего ключа для одной из нескольких родительских таблиц.Решение общего домена первичного ключа
Один из способов, с помощью которого люди иногда решают эту проблему, заключается в использовании одного пула идентификаторов, чтобы не было путаницы для любого данного идентификатора, независимо от того, принадлежит ли он к одному подтипу или другому. Это, вероятно, будет работать вполне естественно в банковском сценарии, поскольку вы не собираетесь выдавать один и тот же номер банковского счета как корпорации, так и физическому лицу. Это имеет то преимущество, что избегает необходимости в атрибуте разделения. Вы можете сделать это с таблицей супер-типа или без нее. Использование таблицы супертипа позволяет использовать декларативные ограничения для обеспечения уникальности. В противном случае это должно быть обеспечено в процедурном порядке. Это решение нормализовано, но оно не позволит вам поддерживать декларативную ссылочную целостность, если вы не сохраните таблицу супертипа. Это все еще не делает ничего, чтобы избежать сложной логики поиска.
Таким образом, вы можете видеть, что на самом деле невозможно иметь чистый дизайн, который бы соответствовал всем правилам, в то же время сохраняя простой поиск данных. Вы должны решить, где ваши компромиссы будут.
источник
corporation_id
иperson_id
тогда у вас, по сути, было бы решение для подтипа, за исключением того, что таблица супертипов была бы разделена на две части, а внешний ключ был бы инвертирован, чтобы люди не могли иметь несколько учетных записей. Этот вид побеждает цель.RefID
иRefTable
гдеRefTable
это фиксированный идентификатор, который идентифицирует целевую таблицу. Существует много вариантов использования этого типа ключа, и очень важно поддерживать 10 или более таблиц связей / подтипов для обеспечения целостности. Для тех случаев я создал этоkey
сам.