Ian*_*lor 6 sql database postgresql schema
我正在尝试在Postgres数据库中建模一些需要"继承"的不同用例,并意识到有多种方法可以做到这一点,我不确定哪种是最好的.
我想到的两个具体用例是:
"成员资格" - 单个"用户"可以是不同类型对象的成员:"团队","集合"或"项目".在这种情况下,成员类型的上限是这三种关系类型.(目前.)
"事件" - 可以创建与我的数据模型中的任何其他对象相关的"事件" - 例如."teams.create","users.update","webhooks.create","items.publish"等.在这种情况下,关系的"类型"并没有真正限制,因为每当我添加新的数据模型时,我很有可能想要为它创建事件.
以下是我可以看到实现这些需求的几种方法......
(对这些代码片段使用"Memberships"用例,但同样的事情也适用于"Events"用例.)
CREATE TABLE memberships (
id TEXT,
user_id TEXT,
team_id TEXT,
collection_id TEXT,
item_id TEXT,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (team_id) REFERENCES teams (id),
FOREIGN KEY (collection_id) REFERENCES collections (id),
FOREIGN KEY (item_id) REFERENCES items (id),
CHECK (
(team_id IS NOT NULL)::integer +
(collection_id IS NOT NULL)::integer +
(item_id IS NOT NULL)::integer = 1
)
);
Run Code Online (Sandbox Code Playgroud)
优点:
JOINs不那么冗长.缺点:
NULL每行都有额外的列值.CHECK约束是有点不可思议?*_id列并更改CHECK.CREATE TABLE memberships (
id TEXT,
user_id TEXT,
target_type TEXT,
target_id TEXT,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id),
CHECK (target_type IN ('team', 'collection', 'items'))
);
Run Code Online (Sandbox Code Playgroud)
优点:
NULL列值.缺点:
JOIN查询有点冗长.CHECK添加新"类型"时必须更改约束.CREATE TABLE team_memberships (
id TEXT,
user_id TEXT,
team_id TEXT,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (team_id) REFERENCES teams (id)
);
CREATE TABLE collection_memberships (
id TEXT,
user_id TEXT,
collection_id TEXT,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (collection_id) REFERENCES collections (id)
);
CREATE TABLE item_memberships (
id TEXT,
user_id TEXT,
item_id TEXT,
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users (id),
FOREIGN KEY (item_id) REFERENCES items (id)
);
Run Code Online (Sandbox Code Playgroud)
优点:
NULL任何行中都没有额外的列值.缺点:
该栏目对方法似乎是普遍存在的,但它意味着数据库不再会自动为你办理外键关系,这似乎是一个相当大的缺点,之类的东西CASCADE不再是一个选项.对我来说,这似乎是一个负面因素,使它成为一个合法的选择.
在多个表的方法也似乎是普遍存在的,而对于"成员"使用情况下,它是有道理的.但对于其他用例,例如"事件"(可以创建与数据库中的任何对象相关的事件,而不是预约束列表),那么拥有如此大量的表似乎不实用.
该XOR列的方法似乎并不普遍,或者至少我无法找到关于它的尽可能多的信息,但感觉像一个很好的平衡,仍然可以让数据库完成所有的工作,而无需添加大量的表.
XOR Columns方法有任何明显的问题吗?
有没有推荐的解决方法?