【问题标题】:Partial "ON DELETE SET NULL" on composite FK复合 FK 上的部分“ON DELETE SET NULL”
【发布时间】:2016-07-20 18:47:15
【问题描述】:

我在 PostgreSQL 数据库中有一组表,将它们命名为 employeecorporationaccountcorporation 有一个指向 account 的外键(“帐户”是一个“企业帐户”,跨越一个或多个公司,而不是用于登录系统的“用户帐户”)和 employee具有corporation 的复合外键和account 的外键(它有两列:corporation_idaccount_idcorporation 的外键使用这两列)。

如果删除employee 的父corporation 行,我希望将其corporation_id 列的值设置为NULL,但account_id 列应保留其值。

这个想法是员工必须“属于”一个帐户(因此employee.account_idNOT NULL),并且可以分配给该帐户内的任何(或没有)公司。如果一个公司被删除,分配给它的任何员工都应该被取消分配(employee.corporation_id 设置为 NULL),但他们仍应“属于”该帐户(employee.account_id 应保留其值)。

将外键上的ON DELETE SET NULL 设置为corporation (id, account_id) 会将corporation_idaccount_id 设置为NULL

【问题讨论】:

    标签: postgresql foreign-keys


    【解决方案1】:

    似乎 postgresql 无法处理。

    如果您只需要一些可以完成工作的东西,我可以想到 2 个解决方法:

    • 为员工和公司之间的连接添加了附加表:
      1. 创建一个包含字段 employee_id、corporate_id、account_id 的表。
      2. 外键 (employee_id, account_id) 参考 employee(corporation_id, account_id) 参考 corporation 与 DELETE级联
      3. 如果要求员工仅在一家公司工作 - 在 (employee_id, account_id) 上添加唯一约束
      4. 最后不会使用员工表中的corporate_id
    • 或从加入中删除 account_id 并使用触发器来验证公司 account_id 是否与员工 account_id 相同

    【讨论】:

      【解决方案2】:

      如果有人仍然感兴趣,还有第三种解决方法:

      1. 首先,为corporate_id FOREIGN KEY (corporation_id) REFERENCES corporation(id) ON DELETE SET NULL 创建一个外键约束。
      2. 其次,为组合键FOREIGN KEY (corporation_id, account_id) REFERENCES corporation(id, account_id) 创建另一个外键约束,只是这次没有ON DELETE

      请注意,创建约束的顺序很重要!因为第二个约束默认为NO ACTION,所以只有在检查约束时仍然存在任何引用行时才会引发错误。但是,因为我们的第一个约束将corporate_id 设置为NULL,所以引用行不再存在并且一切正常。

      【讨论】:

        【解决方案3】:

        我最终为employee (current_account_id) 添加了一个额外的列,用于corporation 的外键,DELETE SET NULLcurrent_account_id = account_id 的检查约束。只有与级联 id 混淆的变化:如果 account.id 更改,它级联到 employee.account_id(通过 employee 的外键到 account)和 employee.current_account_id(通过 employee 的外键到corporation,通过corporationaccount 的外键),并且在某些时候它们是不同的(它们显然不是原子更新的),并且它违反了检查约束,PostgreSQL 不允许延迟.所以我把它改成了一个约束触发器,如果​​值不同,它会引发check_constraint,并且可延迟的(并且最初是延迟的)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-06
          相关资源
          最近更新 更多