我在 PostgreSQL 数据库中有一组表,将它们称为
employee
、corporation
和 account
。 corporation
有一个指向 account
的外键(“帐户”是一个“企业帐户”,跨越一个或多个公司,而不是用于登录系统的“用户帐户”),并且 employee
具有 corporation
的复合外键和 account
的外键(它有两列:corporation_id
和 account_id
;corporation
的外键使用两列)。
如果删除
employee
的父 corporation
行,我希望将其 corporation_id
列的值设置为 NULL
,但 account_id
列应保留其值。
这个想法是,员工必须“属于”一个帐户(因此
employee.account_id
是 NOT NULL
),并且可以分配给该帐户内的任何(或没有)公司。 如果公司被删除,则分配给该公司的任何员工都应取消分配(employee.corporation_id
设置为 NULL
),但他们仍应“属于”该帐户(employee.account_id
应保留其值)。
外键上的 ON DELETE SET NULL
会设置 corporation (id, account_id)
和 corporation_id
为 account_id
。首先,为corporation_id
NULL
FOREIGN KEY (corporation_id) REFERENCES corporation(id) ON DELETE SET NULL
FOREIGN KEY (corporation_id, account_id) REFERENCES corporation(id, account_id)
。
ON DELETE
,因此仅当检查约束时仍然存在任何引用行时才会引发错误。但是,因为我们的第一个约束将corporation_id设置为
NO ACTION
,所以引用行不再存在,并且一切正常。如果你只需要能完成这项工作的东西,我可以想到两种解决方法:
具有用于员工和公司之间连接的附加表:
NULL
(
employee
) 中添加了一个额外的列,用于 current_account_id
的外键,带有 corporation
,以及 DELETE SET NULL
的检查约束。 只有级联 current_account_id = account_id
发生了变化:如果 id
发生了变化,它会级联到 account.id
(通过 employee.account_id
的外键到 employee
)和 account
(通过 employee.current_account_id
的外键到 employee
) corporation
,通过corporation
的外键到account
),并且在某些时候它们是不同的(它们显然不是原子更新的),并且它违反了检查约束,PostgreSQL不允许延迟。 因此,我将其更改为约束触发器,如果值不同,它会引发 check_constraint
,并且 is 可延迟(并且最初是延迟的)。
从 Postgresql v15.0 开始,您可以通过随后指定列列表来指定哪些列设置为 null(即
ON DELETE SET NULL
。因此,对于您的示例,以下内容与您想要的类似:
ON DELETE SET NULL (column_name)