英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论