给定 3 个表(例如posts
、comments
和tags
),有没有办法让其中一个表的外键引用另外两个表之一的主键?
CREATE TABLE IF NOT EXISTS posts (
id UUID DEFAULT uuid_generate_v4 ()
CONSTRAINT posts_pk PRIMARY KEY
);
CREATE TABLE IF NOT EXISTS comments (
id UUID DEFAULT uuid_generate_v4 ()
CONSTRAINT comments_pk PRIMARY KEY
);
CREATE TABLE IF NOT EXISTS tags (
id UUID DEFAULT uuid_generate_v4 ()
CONSTRAINT tags_pk PRIMARY KEY
);
DROP TYPE IF EXISTS s_type;
CREATE TYPE s_type AS ENUM (
'POST',
'COMMENT'
);
CREATE TABLE IF NOT EXISTS tag_mentions (
id UUID DEFAULT uuid_generate_v4 ()
CONSTRAINT tag_mentions_pk PRIMARY KEY,
source_type s_type NOT NULL,
source_id UUID NOT NULL
CONSTRAINT tag_mention_id_fk
-- Is something like this possible?
REFERENCES posts (id) OR comments (id)
);
s_type
也许有一种方法可以通过和posts
和ID之间的复合索引来做到这一点comments
?
这是 SQL 中众所周知的难题,并且没有完全令人满意的解决方案。你会发现很多类似的问题,比如这个。
最好或最不坏的解决方案取决于具体的用例。以下是一些经典方法:
创建两个外键列
tag_mentions
并使用检查约束,确保只有其中一个外键列与设置NOT NULL
匹配source_type
创建一个表,其中
posts_comments
包含来自两个实体的列和一个type
列,而不是两个表,然后使用外键引用该表让外键指向另一个方向,从
posts
和comments
到tag_mentions
第三种解决方案的缺点是您无法阻止 a
posts
和comments
条目与单个 相关tag_mentions
。1. 和 2. 之间的选择通常取决于您的具体情况:如果
posts
和comments
非常相似,则 2. 很有吸引力。另外,如果没有两个类别(posts
和comments
),而是更多,则 2. 可能是更好的解决方案。否则,1. 可能是正确的选择。有用的参考资料