Предположим, что у меня есть две таблицы, Клиент и Поставщик. Я хочу иметь общую таблицу адресов для адресов клиента и поставщика. У клиентов и Поставщиков может оба быть тот ко многим адресам.
Добавьте столбцы для AddressID к Customer
и Vendor
таблицы. Это просто не походит на чистое решение меня.
Customer Vendor Address
-------- --------- ---------
CustomerID VendorID AddressID
AddressID1 AddressID1 Street
AddressID2 AddressID2 City...
Переместите внешний ключ в Address
таблица. Для Клиента, Address.CustomerID
будет заполнен. Для Поставщика, Address.VendorID
будет заполнен. Мне не нравится это ни один - я не должен должен быть изменять таблицу адресов каждый раз, когда я хочу использовать ее для другого объекта.
Customer Vendor Address
-------- --------- ---------
CustomerID VendorID AddressID
CustomerID
VendorID
Я также видел это - только 1 столбец внешнего ключа на Таблице адресов с другим столбцом для идентификации, которому таблице внешнего ключа принадлежит адрес. Мне не нравится этот, потому что это требует, чтобы все таблицы внешнего ключа имели тот же тип идентификатора. Это также кажется грязным, после того как Вы начинаете кодировать против него.
Customer Vendor Address
-------- --------- ---------
CustomerID VendorID AddressID
FKTable
FKID
Так, я просто слишком придирчив, или являюсь там чем-то, о чем я не думал?
Я бы сказал, что недостающая часть головоломки - это отношение "is a", которое часто упускается из виду при моделировании данных; оно отличается от привычного отношения "has a". Отношения "есть" похожи на отношения наследования в объектно-ориентированном дизайне. Для моделирования этой связи вам понадобится базовая таблица, которая представляет общие атрибуты продавцов и клиентов. Например, мы можем назвать базовую таблицу "Организации":
Organizations Vendors Customers
-------------- --------------------- ---------------------
OrganizationID(PK) OrganizationID(FK/PK) OrganizationID(FK/PK)
AddressID1(FK)
AddressID2(FK)
В этом примере поставщик "является" организацией, а клиент "является" организацией, в то время как организация "имеет" адрес. Таблицы Organizations, Vendors и Customers имеют общий ключ и общую последовательность ключей, обеспечиваемую ссылочной целостностью.
Я думаю, что из трех вариантов, которые вы указали, я был бы наиболее склонен выбрать вариант 1. Обычно у клиента или поставщика не более нескольких разных адресов, но если они делают, может быть, решение ниже подойдет вам лучше. Я бы не стал выбирать вариант 2, потому что, вероятно, нет смысла связывать адрес и с покупателем, и с продавцом одновременно. Я знаю, что вы, вероятно, зададите только один из этих идентификаторов за раз, но модель может сбивать с толку, и вам может потребоваться добавить специальную логику, чтобы убедиться, что для любой данной записи установлен только CustomerID или VendorID. Я бы определенно не стал использовать вариант 3, потому что вы не можете сделать FKID настоящим FK. Если вы хотите, чтобы столбец ссылался на несколько таблиц, вы не сможете использовать ограничение FK в базе данных для его принудительного применения.Кроме того, если вы планируете использовать ORM для взаимодействия с базой данных в коде, у них, как правило, возникают проблемы с «поддельными» внешними ключами, которые ссылаются на несколько таблиц в зависимости от отдельного столбца «дискриминатор».
Если вам нужно действительно открытое решение, вы можете создать отношения «многие ко многим» между клиентом и адресом, поставщиком и адресом.
Customer
--------
CustomerID (PK)
Vendor
------
VendorID (PK)
Address
-------
AddressID (PK)
CustomerAddress
---------------
CustomerID (FK/PK)
AddressID (FK/PK)
VendorAddress
-------------
VendorID (FK/PK)
AddressID (FK/PK)
вы можете изменить дизайн таблицы, чтобы она содержала следующие поля:
Address_Type (a flag to say that this is a customer, or a vendor)
ID (a common ID for both customer and vendor and depending on the flag you know what ID it is)
Address (Data of address itself)
или вы можете иметь две таблицы: