【问题标题】:Common one-to-many table for multiple entities多个实体的通用一对多表
【发布时间】:2011-02-21 05:14:50
【问题描述】:

假设我有两个表,客户和供应商。我想要一个用于客户和供应商地址的通用地址表。客户和供应商都可以拥有一对多地址。

选项 1

将 AddressID 的列添加到 CustomerVendor 表中。这对我来说似乎不是一个干净的解决方案。

Customer     Vendor         Address
--------     ---------      ---------
CustomerID   VendorID       AddressID
AddressID1   AddressID1     Street
AddressID2   AddressID2     City...

选项 2

将外键移至Address 表。对于客户,Address.CustomerID 将被填充。对于供应商,Address.VendorID 将被填充。我也不喜欢这样 - 每次我想将地址表用于另一个实体时,我都不需要修改它。

Customer     Vendor         Address
--------     ---------      ---------
CustomerID   VendorID       AddressID
                            CustomerID
                            VendorID

选项 3

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

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

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

【问题讨论】:

    标签: database database-design data-modeling


    【解决方案1】:

    我认为在您提供的三个选项中,我最倾向于选择选项 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)
    

    【讨论】:

      【解决方案2】:

      您能否重新设计表格以包含以下字段:

       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)
      

      或者你可以有两个表:

      • 地址表,其中没有引用地址类型。即同时拥有
        • 实体 ID(键)
        • 地址
      • 地址类型表,它将指向入口并在表外具有标志:
        • 实体 ID(FK 到上表中的实体 ID)
        • 实体类型(客户或供应商)

      【讨论】:

      • 这是我的选择 3。你解释得比我好。我还是想避免它。
      • 如果您使用地址类型标志作为过滤器,可以简化编码。并且您可以在标志和 ID 上使用聚合键来确保唯一性。但如果您试图找到第四个解决方案,请在上面找到修改后的答案
      【解决方案3】:

      我想说这个难题中缺少的部分是数据建模中经常被忽视的“是”关系;这与熟悉的“有”关系不同。 “是”关系类似于面向对象设计中的继承关系。要对此建模,您需要一个表示供应商和客户的共同属性的基表。例如,我们可以将基表称为“Organizations”:

      Organizations       Vendors               Customers
      --------------      ---------------------  ---------------------
      OrganizationID(PK)  OrganizationID(FK/PK)  OrganizationID(FK/PK)
      AddressID1(FK)
      AddressID2(FK)
      

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

      【讨论】:

      • +1 用于 OO 类比。我一直认为这是 OO 中一个非常简单的继承问题,但我不知道如何在数据模型中对其进行建模。我想我可以将您的解决方案与 Andy White 的解决方案结合起来,并提出我正在寻找的一对多关系。
      【解决方案4】:

      如果有四个表,其中一个充当地址的网关? 所以你会有

      Customer
          customerId (PK)
          addressBookId (FK to AddressBook)
      
      Vendor
          vendorId (PK)
          addressBokId (FK to AddressBook)
      
      AddressBook
          addressBookId (PK)
      
      Address
          addressId (PK)
          addressBookId (FK to AddressBook)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-27
        • 1970-01-01
        • 2019-03-08
        • 1970-01-01
        • 2016-01-13
        • 2016-07-23
        • 2021-05-25
        • 1970-01-01
        相关资源
        最近更新 更多