【发布时间】:2020-10-24 23:14:17
【问题描述】:
我正在为其用户开发一个具有多个角色的 Web 应用程序。使用的数据库是 Postgres 10。角色非常不同,并且有很多不重叠的数据,因此通常一个特定的表应该只属于一个角色而不属于另一个角色。
在下面的示例中,我将使用两个角色:seller 和 buyer。第一个角色分配给拥有一些公司并销售商品的用户。第二个角色分配给购买商品并可以收到礼物的用户。 卖家不能接受礼物,买家不能有公司。 seller 和 buyer 都可以有头像。
我正在考虑以下四种设计及其优缺点。
案例一
这里我们有一个 role reference table 枚举系统中的所有角色(seller 或 buyer),user 表,其中包含引用角色表的用户的密码和电子邮件,avatar、company 和 gifts_recieved 表引用 user 表。
专业人士
- 没有表具有可空属性
缺点
- 应该使用触发器来检查参照完整性。例如,如果 id=1 的 user 是 buyer,我们应该阻止向 company 插入一行em> 表,user_id=1。因此,我们应该在 每个 特定于角色的表上创建一个触发器,该触发器引用 user 表以保护参照完整性。
案例 2
这里,user 表包含可为空的角色属性:seller_id 和 buyer_id(或示例中没有的其他角色)。其中只有一个不是 NULL,它定义了用户的角色。所有特定于角色的表都引用 seller 或 buyer 表。两个角色通用的 Avatar 表继续引用 user 表。
专业人士
- 不需要触发器来保护角色特定表的引用完整性:它们都引用 seller 或 buyer 表。
缺点
- 可以为 NULL 的角色属性。
- 需要一个触发器(不是在情况 1 中触发所有表)来确保只有一个角色属性(seller_id 或 buyer_id)不为 NULL 并且所有其他为 NULL。
案例 3
为了避免 NULL-able 角色属性,我们将使用 Postgres 的 inheritance 用于表(MySQL 不支持此功能)。在这里,user 表被“吞噬”到 seller 和 buyer 表中。 Avatar 表已重复并以角色名称为前缀。
专业人士
- 没有可以为 NULL 的角色属性。
- 根本没有触发器。
缺点
- 不同角色通用的表被重复 - 纯粹是资源浪费。
- 继承是 Postgres 特有的功能。
案例4
为了解决案例 3 中的重复问题,将 avatar_id 移动到 seller 和 buyer的 user 表> 继承。因此,对于 seller 和 buyer 共有的每个表,我们将为它们的父表 (user) 添加一个属性。
专业人士
- 没有参照完整性的触发器
- 没有表重复
- 没有可以为 NULL 的属性
缺点
- Postgres 继承有其注意事项:https://www.postgresql.org/docs/10/ddl-inherit.html
问题
上述哪种解决方案适合最佳数据库设计实践(如果有)?用户角色应该是用户表的属性还是特定的表?
澄清
- 一个卖家只能拥有一家公司。
- 通过电子邮件/密码对标识的用户可以是卖家也可以是买家。
【问题讨论】:
-
不清楚是只有一家公司还是几家公司。此外,尚不清楚卖方是否也可以成为客户,如果有多个公司,则公司中的卖方可能是另一家公司的客户。在那种情况下,我会选择案例 1,但没有触发器,并让 Web 应用程序的服务器端做出在案例 1 中使用触发器的决定。无论如何,如果我需要更改数据库提供程序,我会避免继承。设计实践虽然很棘手,但我经常不得不在特定情况下发明自己的实践。
-
卖家只有一家公司,用户可以是卖家也可以是买家。我已对原始问题进行了说明。
标签: postgresql database-design user-roles