Postgres: 引用数组中的外键

huangapple go评论67阅读模式
英文:

Postgres: Referencing a foreign key that's part of an array

问题

使用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_id是我的media表中的主键。

上述SQL代码无法工作,因为出现了以下问题:

  CONSTRAINT fk_media 
    FOREIGN_KEY(media_id) 
      REFERENCES media(media_id)

我理解为什么会出错。我尝试用以下内容替换原来的第3行:media_ids media_id[] NOT NULL, 但那也不起作用。

我已经阅读了一些信息,有些人建议使用桥接表。虽然我理解这种思路,但这个shared_media表除了提供其包含的数据之外,几乎不会被访问。换句话说,它永远不会被搜索,这就是为什么我愿意使用media_ids uuid[]方法的原因。

删除fk_media约束允许创建表格。鉴于我要在自己的项目中使用shared_media来做什么,你对这种方法满意吗?

英文:

With Postgres, I've created many tables that have foreign key references but they've always had a 1:1 relationship. Now I'd like to do something a little different:

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)
);

The 3rd line refers to an array of media_id values; media_id being the primary key in my media table.

The SQL code above fails to work because of:

  CONSTRAINT fk_media 
    FOREIGN_KEY(media_id) 
      REFERENCES media(media_id)

I understand why. I tried substituting the original 3rd line with: media_ids media_id[] NOT NULL, but that didn't work either.

I've done some reading and a bridge table is suggested by some. While I understand this thinking, this shared_media table will rarely be accessed other than providing the data it contains. In other words, it'll never be searched, which is why I'm comfortable using the media_ids uuid[] approach.

Dropping the fk_media constraint does allow the table to be created. Given what I'm going to use shared_media for, would you be happy with this approach in your own project?

答案1

得分: 2

不要在数组中存储引用;请使用关联(桥接)表。此建议基于参照完整性和代码维护的考虑。数据查询或搜索的频率并不重要。

使用带有适当外键约束的关联表可以利用数据库平台的本机参照完整性支持。这种方法还使模式自我记录,因为可以通过查询系统目录和视图来确定表之间的关联关系。

虽然可能在数组中存储引用并使用触发器提供参照完整性支持,但这种方法需要更多的编码工作,并提供了许多引入缺陷的机会。这种方法还使其他人更难熟悉设计,因为关联关系是在代码和外部文档中捕获的,而不是模式的固有元素。

原始表定义中的media_ids上的NOT NULL约束可以替换为延迟的语句触发器,以确保在提交事务时至少存在一个media引用。

英文:

Do not store references in arrays; use associative (bridge) tables. This recommendation is based on referential integrity and code maintenance concerns. How often the data is queried or searched is not relevant.

Using an associative table with appropriate foreign key constraints takes advantage of the database platform's native referential integrity support. This approach also makes the schema self-documenting since the associations between tables can be ascertained by querying the system catalogs and views.

While it is possible to store references in arrays and use triggers to provide referential integrity support, such an approach requires significantly more coding effort and presents many opportunities to introduce defects. This approach also makes it more difficult for others to become familiar with the design since the associations are captured in code and external documentation instead of being inherent elements of the schema.

The NOT NULL constraint on media_ids that is in the original table definition could be replaced with a deferred after statement trigger to insure that at least one media reference is present when the transaction is committed.

答案2

得分: 1

你正在尝试使用uuid[]来引用uuid,但外键引用需要匹配的数据类型。

Postgres中未实现数组元素的外键引用(不确定其他RDBMS是否实现)。请参考:

要么保留数组并放弃强制引用完整性。可以使用触发器来实现解决方法,但不如简单、安全和便宜。以下是相关案例和代码示例:

要么使用"桥接表"来规范化设计,这是一个适当的多对多实现,始终强制执行引用完整性。请参考:

另外,media_ids uuid[] NOT NULL 不会强制要求“至少一个”引用。数组仍然可以为空([])。不确定这是否符合意图。

英文:

You are trying to reference uuid with uuid[]. But a FK reference requires matching data types.

Foreign key references for array elements are not implemented in Postgres. (Not sure if any other RDBMS implements that.) See:

Either keep the array and give up enforcing referential integrity. There are workarounds with triggers, but not nearly as simple, safe and cheap. A related case with code example:

Or normalize your design with a "bridge table" - a proper many-to-many implementation that enforces referential integrity at all times. See:

Aside, media_ids uuid[] NOT NULL does not enforce "at least one" reference. The array can still be empty ([]). Not sure if that's the intention.

huangapple
  • 本文由 发表于 2023年6月19日 01:25:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76501761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定