用户和组:3或2个表(SQL)

时间:2013-09-23 22:15:25

标签: mysql sql database database-design

我想知道将我的用户及其群组存储在3个表和2个表中的利弊。

2桌的优点

  1. 这些群体可以很容易地成为用户自己,并且在大多数情况下似乎与用户共享所有相同的字段,即姓名,图片,密码,电子邮件。
  2. 3个表的优点

    1. 拥有第3个groups表将更加明确,因此开发人员可能更容易理解/维护。
    2. 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**
      

      注意: user_id表中的group_idgroup_member都是 引用user_id表格中的users

2 个答案:

答案 0 :(得分: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&amp; group个实体共享 lot 数据(例如,它们可以拥有其他对象,拥有个人资料页面等),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和&amp; group 扩展该基类/表。
  • 使用外键仍然可以强制执行组或用户
  • 如果用户或组获取特定数据,则无需向表中添加对大部分记录无用的列,它可以存储在特定于类型的表中。

一些缺点:

  • 无法强制实体是用户或组,但不能 none (无类型)
  • 除非您存储冗余列type(或is_group / is_user),否则确定实体是组还是用户需要JOIN,但是在两边的主键上,开销应该很小

答案 1 :(得分:2)

如果有的话,我认为group_member将是可选表。如果用户之间需要多对多关系,则需要此表。换句话说,如果用户可以属于多个组,则您需要一个可以将user_id链接到group_id的表格。如果用户只能属于一个组,您可能仍然想要一个groups表,然后拥有一个{ group_id表格上的{1}}列。

但是,要回答原始问题,如果您将组信息(例如组名称)存储在users表中,则必须为组内的每个用户重复此数据。您有许多具有相同组名的行,如果您希望以后更改组名称,则必须更新许多行而不是一行。它也很难说出同一组中的谁,并且很多这类查询会变得非常低效。

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