Database 多个实体的通用一对多表

Database 多个实体的通用一对多表,database,database-design,data-modeling,Database,Database Design,Data Modeling,假设我有两张桌子,客户和供应商。我想为客户和供应商地址创建一个公共地址表。客户和供应商都可以有一对多的地址 选择1 将AddressID列添加到客户和供应商表中。对我来说,这似乎不是一个干净的解决方案 Customer Vendor Address -------- --------- --------- CustomerID VendorID AddressID AddressID1 AddressID1 Street Ad

假设我有两张桌子,客户和供应商。我想为客户和供应商地址创建一个公共地址表。客户和供应商都可以有一对多的地址

选择1 将AddressID列添加到
客户
供应商
表中。对我来说,这似乎不是一个干净的解决方案

Customer     Vendor         Address
--------     ---------      ---------
CustomerID   VendorID       AddressID
AddressID1   AddressID1     Street
AddressID2   AddressID2     City...
选择2 将外键移动到
地址
表。对于客户,将填充
地址.CustomerID
。对于供应商,将填充
地址.VendorID
。我也不喜欢这样-我不需要每次想将地址表用于另一个实体时都修改它

Customer     Vendor         Address
--------     ---------      ---------
CustomerID   VendorID       AddressID
                            CustomerID
                            VendorID
选择3 我也看到了这一点——地址表上只有一个外键列,另一列用于标识地址所属的外键表。我不喜欢这个,因为它要求所有外键表都具有相同类型的ID。一旦开始对它进行编码,它看起来也很混乱

Customer     Vendor         Address     
--------     ---------      ---------
CustomerID   VendorID       AddressID
                            FKTable
                            FKID

那么,是我太挑剔了,还是有什么我没有想到的呢?

我认为在你给出的三个选项中,我最倾向于选择选项1。通常情况下,客户或供应商的地址不会超过几个,但如果他们有,也许下面的解决方案对您更有效。我不会选择选项2,因为同时将地址与客户和供应商关联可能没有意义。我知道您可能一次只设置其中一个ID,但是模型可能会混淆,并且您可能需要添加特殊的逻辑,以确保在任何给定记录上只设置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)
或者您可以有两个表:

  • 地址表,其中没有对地址类型的引用。i、 两者兼得
    • 实体ID(密钥)
    • 地址
  • 地址类型表,其中它将指向入口,并在表外具有标志,以便:
    • 实体ID(上表中FK到实体ID)
    • 实体类型(客户或供应商)

我想说,谜题中缺失的一块是“是一个”关系,在数据建模中经常被忽略;这不同于熟悉的“有一个”关系。“是”关系类似于面向对象设计中的继承关系。要对此进行建模,您需要一个表示供应商和客户的公共属性的基表。例如,我们可以将基表称为“组织”:


在本例中,供应商“是”组织,“客户”是“组织”,而组织“有”地址。组织、供应商和客户表共享一个公共密钥和一个由引用完整性强制执行的公共密钥序列。

四个表中的一个作为地址的网关如何? 所以你会

Customer
    customerId (PK)
    addressBookId (FK to AddressBook)

Vendor
    vendorId (PK)
    addressBokId (FK to AddressBook)

AddressBook
    addressBookId (PK)

Address
    addressId (PK)
    addressBookId (FK to AddressBook)

这是我的选择3。你解释得比我好。我仍然想避免它。如果使用地址类型标志作为过滤器,编码可以简化。您可以使用flag和ID上的聚合键来确保唯一性。但是,如果您试图找到第四个解决方案,请在OO类比中找到+1以上的修改答案。我一直认为这是OO中一个非常简单的继承问题,但我不知道如何在数据模型中建模。我想我可以把你的解决方案和安迪·怀特的结合起来,找到我想要的一对多的关系。
Customer
    customerId (PK)
    addressBookId (FK to AddressBook)

Vendor
    vendorId (PK)
    addressBokId (FK to AddressBook)

AddressBook
    addressBookId (PK)

Address
    addressId (PK)
    addressBookId (FK to AddressBook)