假设我有一个项目表:
CREATE TABLE items
(
item serial PRIMARY KEY,
...
);
Run Code Online (Sandbox Code Playgroud)
现在,我想为每个项目介绍“权限”的概念(请注意,我在这里不是在谈论数据库访问权限,而是该项目的业务逻辑权限)。每个项目都具有默认权限以及可以覆盖默认权限的每用户权限。
我试图想出几种方法来实现这一点,并提出了以下解决方案,但我不确定哪个是最好的以及为什么:
为每个权限使用布尔列:
CREATE TABLE items
(
item serial PRIMARY KEY,
can_change_description boolean NOT NULL,
can_change_price boolean NOT NULL,
can_delete_item_from_store boolean NOT NULL,
...
);
CREATE TABLE item_per_user_permissions
(
item int NOT NULL REFERENCES items(item),
user int NOT NULL REFERENCES users(user),
PRIMARY KEY(item, user),
can_change_description boolean NOT NULL,
can_change_price boolean NOT NULL,
can_delete_item_from_store boolean NOT NULL,
...
);
Run Code Online (Sandbox Code Playgroud)
优点:每个权限都是命名的。
缺点:有几十个权限会显着增加列数,并且您必须定义它们两次(每个表中一次)。
使用整数并将其视为位域(即位 0 …
假设您有这样的nodes
表:
CREATE TABLE nodes
(
node serial PRIMARY KEY,
parent integer NULL REFERENCES nodes(node),
ts timestamp NOT NULL DEFAULT now()
);
Run Code Online (Sandbox Code Playgroud)
它代表了一个标准的类似节点的树结构,根节点在顶部,几个子节点悬挂在根节点或其他子节点上。
让我们插入几个示例值:
INSERT INTO nodes (parent)
VALUES (NULL), (NULL), (NULL), (NULL), (1), (1), (1), (1), (6), (1)
, (6), (9), (6), (6), (3), (3), (3), (15);
Run Code Online (Sandbox Code Playgroud)
现在我想检索前 10 个根节点及其所有子节点,深度为 4:
WITH RECURSIVE node_rec AS
(
(SELECT 1 AS depth, * FROM nodes WHERE parent IS NULL LIMIT 10)
UNION ALL
SELECT depth + 1, n.*
FROM nodes …
Run Code Online (Sandbox Code Playgroud) 假设您有一张桌子groups
和一张桌子item
。每个项目都属于一个组。它是该群体的固有组成部分。一个项目不能存在于一个组之外,也不能移动到另一个组中。
当试图决定item
表的主键时,我应该使用什么?
我应该像这样组成一个人工全局序列键:
CREATE TABLE items
(
item serial PRIMARY KEY,
group integer NOT NULL REFERENCES groups(group),
);
Run Code Online (Sandbox Code Playgroud)
...或者我应该使用复合键和每组项目序列,如下所示:
CREATE TABLE items
(
group integer NOT NULL REFERENCES groups(group),
item integer NOT NULL,
PRIMARY KEY(group, item)
);
Run Code Online (Sandbox Code Playgroud)
我更倾向于第二种解决方案的原因是帖子 URL 将始终显示组和项目,因此将它们都作为复合主键是有意义的。在第一种解决方案的情况下,URL 包含多余的信息,因为组 ID 已经可以单独从项目 ID 中推导出来。但是,URL 结构是给定的,不能更改。
第二种解决方案的缺点是您必须管理每个组的序列(即每个组的每个项目整数应从 0 开始)。
在最佳实践、规范化和性能方面哪个更好?或者这只是品味问题?