使用 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)
我明白为什么。我尝试用:
media_ids media_id[] NOT NULL
替换原来的第三行,但这也不起作用。
我读过一些书,有些人建议使用桥接表。虽然我理解这种想法,但除了提供它包含的数据之外,很少会访问这个
shared_media
表。换句话说,它永远不会被搜索到,这就是为什么我很乐意使用 media_ids uuid[]
方法。
删除
fk_media
约束确实允许创建表。鉴于我将使用 shared_media
来做什么,您对自己项目中的这种方法感到满意吗?
您正在尝试用
uuid
引用 uuid[]
。但 FK 引用需要匹配的数据类型。
Postgres 中未实现数组元素的外键引用。 (不确定是否有任何其他 RDBMS 实现了这一点。)参见:
要么 保留数组并放弃强制引用完整性。有一些带有触发器的解决方法,但远没有那么简单、安全和便宜。相关案例及代码示例:
或者 使用“桥接表”标准化您的设计 - 一种适当的多对多实现,始终强制执行引用完整性。参见:
此外,
media_ids uuid[] NOT NULL
不强制执行“至少一个”引用。数组仍然可以为空 ([]
)。不确定是否是这个意图。
不要将引用存储在数组中;使用关联(桥接)表。此建议基于引用完整性和代码维护问题。查询或搜索数据的频率并不相关。
使用具有适当外键约束的关联表可以利用数据库平台的本机引用完整性支持。这种方法还使模式能够自记录,因为可以通过查询系统目录和视图来确定表之间的关联。
虽然可以将引用存储在数组中并使用触发器来提供引用完整性支持,但这种方法需要更多的编码工作,并且存在许多引入缺陷的机会。这种方法还使得其他人更难以熟悉设计,因为关联是在代码和外部文档中捕获的,而不是架构的固有元素。
原始表定义中对
NOT NULL
的 media_ids
约束可以替换为延迟的 after 语句触发器,以确保提交事务时至少存在一个 media
引用。