postgresql Postgres:引用数组中的外键

8ehkhllq  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(2)|浏览(187)

使用Postgres,我创建了许多具有外键引用的表,但它们总是具有1:1的关系。现在我想做一些不同的事情:

CREATE TABLE public.shared_media (
  share_id uuid NOT NULL UNIQUE DEFAULT uuid_generate_v4(),
  media_ids uuid[] NOT NULL,
  description text NULL,
  intro_message text NULL,
  embedded bool NOT NULL,
  export_options json NULL,
  user_id uuid NOT NULL,
  date_created timestamptz NOT NULL DEFAULT now(),
  date_deleted timestamptz NULL,
  CONSTRAINT fk_media 
    FOREIGN_KEY(media_id) 
      REFERENCES media(media_id)
    CONSTRAINT fk_users
      FOREIGN KEY(user_id)
          REFERENCES users(user_id)
);

第3行是指media_id值的数组; media_idmedia表中的主键。
上面的SQL代码无法工作,原因是:

CONSTRAINT fk_media 
    FOREIGN_KEY(media_id) 
      REFERENCES media(media_id)

我明白为什么。我试着把原来的第三行替换为:media_ids media_id[] NOT NULL,,但它也不起作用。
我读过一些书,有人建议用桥牌表。虽然我理解这种想法,但除了提供它包含的数据外,这个shared_media表很少被访问。换句话说,它永远不会被搜索,这就是为什么我喜欢使用media_ids uuid[]方法。
删除fk_media约束确实允许创建表。考虑到我将使用shared_media来做什么,您会在自己的项目中对这种方法感到满意吗?

tktrz96b

tktrz96b1#

不要在数组中存储引用;使用关联(桥接)表。此建议基于引用完整性和代码维护问题。查询或搜索数据的频率并不相关。
使用具有适当外键约束的关联表可以利用数据库平台的本机引用完整性支持。这种方法还使模式自文档化,因为表之间的关联可以通过查询系统目录和视图来确定。
虽然可以将引用存储在数组中并使用触发器来提供引用完整性支持,但这种方法需要更多的编码工作,并有许多引入缺陷的机会。这种方法还使得其他人更难熟悉设计,因为关联是在代码和外部文档中捕获的,而不是模式的固有元素。
原始表定义中对media_idsNOT NULL约束可以替换为延迟的after语句触发器,以确保在提交事务时至少存在一个media引用。

qgelzfjb

qgelzfjb2#

您正在尝试使用uuid[]引用uuid。但是FK引用需要匹配的数据类型。

Postgres不支持数组元素的外键引用。(不确定是否有其他RDBMS实现了这一点。)请参阅:

  • PostgreSQL数组可以优化连接吗?
    或者保留数组并给予强制引用完整性。触发器有一些变通方法,但远没有那么简单、安全和便宜。一个相关案例与代码示例:
  • PostgreSQL可以对数组元素有唯一性约束吗?
    或者使用“桥接表”规范化您的设计-这是一种适当的多对多实现,始终强制引用完整性。参见:
  • 如何在PostgreSQL中实现多对多关系?

此外,media_ids uuid[] NOT NULL不强制“至少一个”引用。数组仍然可以为空([])。我不确定这是不是本意。

相关问题