0

我想知道将我的用户及其组存储在 3 个表与 2 个表中的优缺点。

2张桌子的优点

  1. 这些组很容易只是用户本身,并且在大多数情况下似乎与用户共享所有相同的字段,即姓名、图片、密码、电子邮件。

3张桌子的优点

  1. 拥有第三groups张表会更明确,因此开发人员可能更容易理解/维护。

3 个表的缺点 1. 通过不执行上面“2 个表的优点”中的 #1 来违反应用程序代码中的 DRY 原则。

我还应该考虑什么?

2 个强制表是一个users表和一个group_member表。

+---------+      +------------+
| users    |      | group_member |     +----------+
+---------+      +------------+     | groups    |
| user_id |----->| user_id    |     +----------+
| name    |      | group_id   |<----| group_id |
| pass    |      +------------+     | name     | 
| ...     |                         | ...      |
+---------+                         +----------+

                                    **theoretical 3rd table**

注意:表中的 the和user_idthe都指的是表中的group_idgroup_memberuser_idusers

4

2 回答 2

3

要点:如果您想将用户和组存储在一个表中,因为它们共享(大多数)特征,这是完全有效的。但是,这意味着从技术上讲,组可以是用户的成员,并且您不能在数据库级别强制用户可以在组中,而不是相反:

1表中的场景:

CREATE TABLE users_and_groups (id int...
CREATE TABLE group_members (
    group_id, 
    user_id
    FOREIGN KEY (group_id) REFERENCES users_and_group (id) -- no way to limit on only groups
    FOREIGN KEY (user_id) REFERENCES users_and_group (id) -- no way to limit on only users   
)

2个表中的场景:

CREATE TABLE users (id int...
CREATE TABLE groups (id int...
CREATE TABLE group_members (
    group_id, 
    user_id
    FOREIGN KEY (group_id) REFERENCES groups (id) -- guarantees a group
    FOREIGN KEY (user_id) REFERENCES users (id)   -- guarantees a user
)

如果出现应用程序级别的错误,像这样防御性地设置数据库可以防止很多伤害。


但是,如果user&group实体共享大量数据(例如,都可以拥有其他对象,拥有个人资料页面等),则 4 表解决方案可以很好地工作:

CREATE TABLE users_and_groups (id, ...shared data...
CREATE TABLE users (users_and_groups_id, ...user specific data...
CREATE TABLE groups (users_and_groups_id, .. group specific data...
CREATE TABLE group_members (
    group_id, 
    user_id
    FOREIGN KEY (group_id) REFERENCES groups (users_and_groups_id) -- guarantees a group
    FOREIGN KEY (user_id) REFERENCES users (users_and_groups_id)   -- guarantees a user
)

这有几个优点:

  • 允许组或用户的外键可以在 1 列中。
  • 在应用程序级别,这是经典的继承:一个基类users_and_groups扩展user该基类/表。group
  • 使用外键仍然可以强制执行组或用户
  • 如果用户或组获得特定数据,则无需在表中添加对大部分记录无用的列,可以将其存储在特定类型的表中。

一些缺点:

  • 不可能强制一个实体要么是用户要么是组,但不能同时是两者都不是(无类型)
  • 除非您存储冗余列type(或is_group/ is_user),否则确定实体是组还是用户需要 a JOIN,但由于这在双方的主键上,开销应该很小
于 2013-09-23T22:36:41.467 回答
2

如果有的话,我认为group_member将是可选表。如果您需要用户组之间的多对多关系,则只需要此表。换句话说,如果一个用户可以属于多个组,那么您需要一个可以将 a 链接到 a的表。如果一个用户只能属于一个组,您可能仍然需要一个表,然后在表上有一列。user_idgroup_idgroupsgroup_idusers

但是,要回答您最初的问题,如果您将组信息(例如组名称)存储在group_member表中,则必须为组中的每个用户重复此数据。您将有许多行具有相同的组名,如果您想稍后更改组名,则必须更新许多行而不仅仅是一个行。这也使得分辨谁在同一个组中变得非常困难,并且许多此类查询将变得非常低效。

groups无论您使用一张还是两张表,将您的不同组规范化为一张表绝对是正确的方法。

于 2013-09-23T22:22:33.360 回答