PostgreSQL中的外键+表继承?

35

我有三个表:organizationorganization_teamsorg_users。其中 organization_teams 是从 organization 继承而来的。如果在 organization_teams 中添加记录,它将使用 organization 表的 id 值作为 organization_teams 表中的 id 列的值。

org_users 的外键是 organization 表的 id 列。现在当我尝试向 org_users 插入数据时,会出现以下错误:

insert or update on table "org_users" violates foreign key constraint "org_users_organizations"
DETAIL:  Key (org_id)=(12) is not present in table "organizations"

为什么?


不,序列不会被继承。 - frlan
3
已知缺陷:继承特性的一个严重限制是索引(包括唯一约束)和外键约束只适用于单个表,而不适用于其继承子表。 来源链接:http://www.postgresql.org/docs/current/static/ddl-inherit.html#DDL-INHERIT-CAVEATS - pozs
我已经在Organization表中有一些组织,还有一些在organization_teams中。所以org_user在organizations上有外键。 - Supriya Pansare
3个回答

40

这在用户手册中有详细介绍

简言之,您可以使用外键或表继承,但不能同时使用。这并非本质上不可能,只是在 PostgreSQL 中实现跨继承表的唯一索引以快速、可靠地实现比较困难。如果没有唯一索引,就无法使用有用的外键。迄今为止,还没有人成功地实现了足够好的支持补丁,以便将其添加到 PostgreSQL 中。

外键可以指向继承层次结构的一部分,但它只会精确查找该表中的行,而不会查找任何父表或子表中的行。要查看外键查找到的哪些行,请执行 SELECT * FROM ONLY thetable。关键字 ONLY 表示 "忽略继承",这也是外键查找所进行的操作。


仅在表继承层次结构的“叶子”表上应用外键是否“安全”? - Andrew Wolfe
如果引用和被引用的表在相同的键上进行分区,则可以在对应的分区之间拥有外键。就是这样。 - Craig Ringer

4
我找到的唯一解决方法是:
  1. 创建一个返回触发器的函数,用于检查继承表中某个ID是否存在
  2. 创建一个约束触发器代替外键
请注意,不要删除原始HTML标签。

1

完全同意@Craig Ringer的观点,我们不能在继承中使用外键。

但是,如果我们确定要插入正确的数据,并且想在org_users中使用外键,我们可以做一件事情。

我们可以创建一个名为org_users_child的org_users子表(没有外键),如下所示:

CREATE TABLE org_users_child () INHERITS (org_users);

现在我们可以在这个子表中插入数据。
现在,如果我们查询org_users表,就能找到想要的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接