Postgresql:角色oid的外键

Posted

技术标签:

【中文标题】Postgresql:角色oid的外键【英文标题】:Postgresql: foreign key to role oid 【发布时间】:2013-02-25 13:09:59 【问题描述】:

如何在 postgres 中为数据库角色添加外键?

CREATE TABLE "public"."role_info" (
    "last_login" timestamptz,
    "user" name,
    CONSTRAINT "role_info" FOREIGN KEY ("user") REFERENCES "pg_catalog"."pg_authid" ("rolname") ON UPDATE NO ACTION ON DELETE NO ACTION
 )
 WITH (OIDS=FALSE);

这将返回权限被拒绝

【问题讨论】:

【参考方案1】:

你没有。您不能在当前实现中添加引用系统目录的外键。

即使稍后对某些目录放宽该限制,所有 DB 共享的全局目录(如 pg_role)也可能仍然受到限制。

可以使用触发器来单向强制关系,阻止您添加引用不存在的系统目录条目的值。但是,您无法阻止目录条目被删除,因此它的实用性有限。

围绕 PostgreSQL 12 版本编辑 2019:

你不能这样做的原因有很多。

系统特殊情况系统目录关系以多种方式使它们表现得特别:

它有时会对它们进行就地更新,这对于用户关系是不允许的,并且不能在事务中止时回滚 它通常通过一层间接和缓存(syscache 和 relcache)访问它们 它通过一种特殊的轻量级访问方法 (genam) 对其进行更新,该方法不支持大量 PostgreSQL 的高级功能,并出于性能、内存使用和代码复杂性的原因做出了许多简化假设。

此外,在pg_catalog.pg_authid 的情况下,它是一个共享关系,您可以通过检查select relisshared from pg_catalog.pg_class where oid = 'pg_catalog.pg_authid'::regclass 看到。这意味着相同的表内容被映射到 PostgreSQL 实例(“集群”或数据目录)上的所有数据库中。没有明智的方法来对此进行 FK,因为引用它的关系将仅存在于 一个数据库pg_catalog.pg_class 中,包含其行的堆也将存在 - 但 引用 pg_catalog.pg_authid 堆将被映射到所有数据库。连接到一个数据库的 postgres 后端将不知道 FK 约束甚至存在于另一个数据库上,也无法检查。

【讨论】:

嗨 Craig,您知道最近的版本(v11、v12)中是否更改了此限制?是否有更详细的记录/解释的地方? 不,它没有改变。我不知道有什么地方可以更详细地记录它,但可能有源代码 cmets 可以。我没有仔细观察那个区域。 根据我从其他工作中了解到的情况,我已经编辑添加了一些原因的解释

以上是关于Postgresql:角色oid的外键的主要内容,如果未能解决你的问题,请参考以下文章

具有意外相似重复的 postgres 用户表导致另一个表具有混乱的外键,如何修复和合并外键?

据我所知,postgres 中的外键约束违规不应该发生。 (带休眠)

Postgresql多个表具有相同的外键唯一约束

PostgreSQL中复合类型列子列的外键约束

PostgreSQL 行级安全性涉及与其他表的外键

单个查询中的 Postgresql 多个连接,其中连接的外键不存在于所有表中