【问题标题】:Creating a one-to-one relationship between tables with an existing one-to-many relationship在具有现有一对多关系的表之间创建一对一关系
【发布时间】:2012-03-19 18:45:18
【问题描述】:

所以我的数据库中有这两个表:

Companies
--------------------
CompanyID (PK)
Name


Employees
--------------------
EmployeeID (PK)
CompanyID (FK)
Name

基本上,一家公司有很多员工。

但我希望每家公司都只有一名员工作为主要联系人。我最初的想法是在Companies 表中添加一个MainContactID 字段,该字段引用Employees 中的EmployeeID,但这会创建一个包含关系的循环。

最好的方法是什么?

【问题讨论】:

    标签: sql sql-server database database-design relational-database


    【解决方案1】:

    您最初的想法没有任何问题(在我看来)。

    虽然你说的有一个循环,但这里没有问题。

    拥有companies.MainContactEmployeeID 可确保每个公司只有一个这样的联系人。

    然后,添加 Companies(CompanyID,MainContactEmployeeID) : Employees(CompanyID,EmployeeID) 的外键可确保该员工实际为该公司工作。 (还需要 Employee 表上的匹配唯一索引)。

    这样的外键只有在“循环”的作用下才有可能。这当然不是问题。

    【讨论】:

    • 这样会造成循环引用的情况,员工已经是Company的子节点,不能同时是父节点,否则无法插入记录。
    • @HLGEM - 我不同意,这是我使用过的模式,它确实有效。 1. 创建没有 MainContact (NULL FK) 的公司。 2. 为该公司创建子员工。 3. 将公司的主要联系人更新为您创建的一名员工。
    【解决方案2】:

    我们对地址、电子邮件和电话做了类似的事情。我们有一个字段将记录标记为主要记录。然后通过触发器维护该字段,以便如果主要联系人更改,您仍然只有一个,如果主要联系人被删除,触发器使用业务规则来确定剩余的哪条记录将获得标志,因为我们必须如果我们有任何记录,至少有一个主要记录。

    【讨论】:

      【解决方案3】:

      我个人更喜欢这个模型:

      Organization
      -------------
      organization_id
      name
      other_columns
      
      Person
      -------------
      person_id
      name
      other_columns
      
      Person_Organization
      --------------------
      person_id
      organization_id
      begin_date
      end_date
      relationship_cd
      

      这允许人们一次为多个组织工作(当然可能)并允许您在关系定义上非常灵活 - 所以此时此人与该组织的“关系”如何......(对承包商等很重要)

      【讨论】:

      • 您将如何强制“最多 1 名员工作为主要联系人”?
      • 可能有多种方法——您可以对 Person_Organization 采用约束或插入/更新触发器来强制执行“Max 1 Employee”。我认为以这种方式强制执行这一点具有很大的可扩展性,而不是将其直接烘焙到表结构中。
      【解决方案4】:

      如果你不想拥有

      • FK 关系中的循环路径
      • FK 列中的空值

      你可以用这个:

      Employee(CompanyID, EmployeeID) 中添加UNIQUE 约束并创建另一个表:

      Company_MainContact
      --------------------
      CompanyID  (PK) (FK1-->Employee)
      EmployeeID      (FK1-->Employee)
      

      【讨论】:

        【解决方案5】:

        使用组合主键创建表,如下所示:

        Company_MainContact
        --------------------
        EmployeeID (PK) (FK-->Employee)
        CompanyID (PK)  (FK-->Company)
        

        【讨论】:

        • 虽然这确实有效并且有其自身的优点,但我认为 OP 对 why 的兴趣与提议的选项一样多。当总是 1:1 时,你有理由这样做吗?
        • 假设数据库已经填充,并且“工作”和这个主要联系人标识符是一个新要求,这可能是最快和最简单的解决方案,不需要 1) 重构数据模型, 或 2) 与触发器等有关的丑陋黑客攻击等。
        • 此解决方案并非 100% 正确。这样,一家公司的主要联系人可以是为另一家公司工作的人。
        • 另外,一个公司可以通过这种方式拥有多个主要联系人。
        • @ypercube 两个优点 :) 需要某种类型的输入验证或触发器来保持一致性。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多