Mysql 用户和组:3或2个表(SQL)
我想知道将我的用户及其组存储在3个表和2个表中的利弊 两张表的优点Mysql 用户和组:3或2个表(SQL),mysql,sql,database,database-design,Mysql,Sql,Database,Database Design,我想知道将我的用户及其组存储在3个表和2个表中的利弊 两张表的优点 这些组可能只是用户本身,在大多数情况下似乎与用户共享所有相同的字段,即姓名、图片、密码、电子邮件 三张表的优点 拥有第三个组表将更加明确,因此开发人员可能更容易理解/维护 三张表的缺点 1.在应用程序代码中违反DRY原则,不执行上面“两个表的优点”中的#1 我还应该想些什么 这两个必填表是用户表和组成员表 +---------+ +------------+ | users | | group_memb
组
表将更加明确,因此开发人员可能更容易理解/维护用户
表和组成员
表
+---------+ +------------+
| users | | group_member | +----------+
+---------+ +------------+ | groups |
| user_id |----->| user_id | +----------+
| name | | group_id |<----| group_id |
| pass | +------------+ | name |
| ... | | ... |
+---------+ +----------+
**theoretical 3rd table**
+-----------++------------+
|用户| |组|成员|+----------+
+---------++-------------+|组|
|用户识别号------->用户识别号+----------+
|name | | group_id |如果有的话,我认为group_member
将是可选的表。只有在用户和组之间需要多对多关系时,才需要此表。换句话说,如果一个用户可以属于多个组,那么您需要一个可以将用户id
链接到组id
的表。如果用户只能属于一个组,您可能仍然需要一个groups
表,然后在users
表上有一个group\u id
列
+---------+ +------------+
| users | | group_member | +----------+
+---------+ +------------+ | groups |
| user_id |----->| user_id | +----------+
| name | | group_id |<----| group_id |
| pass | +------------+ | name |
| ... | | ... |
+---------+ +----------+
**theoretical 3rd table**
但是,为了回答您最初的问题,如果您将组信息(如组名)存储在group\u member
表中,则必须为组中的每个用户重复此数据。您将有许多行具有相同的组名,如果您想稍后更改组名,则必须更新多行而不是一行。这也使得很难区分谁在同一个组中,而且很多这样的查询将变得非常低效
将不同的组规范化为单个组表绝对是正确的方法,无论您使用的是一个表还是两个表。如果有的话,我认为组成员
将是可选的表。只有在用户和组之间需要多对多关系时,才需要此表。换句话说,如果一个用户可以属于多个组,那么您需要一个可以将用户id
链接到组id
的表。如果用户只能属于一个组,您可能仍然需要一个groups
表,然后在users
表上有一个group\u id
列
+---------+ +------------+
| users | | group_member | +----------+
+---------+ +------------+ | groups |
| user_id |----->| user_id | +----------+
| name | | group_id |<----| group_id |
| pass | +------------+ | name |
| ... | | ... |
+---------+ +----------+
**theoretical 3rd table**
但是,为了回答您最初的问题,如果您将组信息(如组名)存储在group\u member
表中,则必须为组中的每个用户重复此数据。您将有许多行具有相同的组名,如果您想稍后更改组名,则必须更新多行而不是一行。这也使得很难区分谁在同一个组中,而且很多这样的查询将变得非常低效
无论您使用的是一个表还是两个表,将不同的组规范化为单个组表绝对是正确的方法。要点:如果您希望将用户和组存储在一个表中,因为它们共享(大多数)特征,这是完全有效的。但是,这意味着从技术上讲,一个组可以是用户的一个成员,而您不能在数据库级别强制执行用户可以在组中,而另一个则不必担心:
表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
)
两个表中的场景:
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
)
如果在应用程序级别出现bug,那么像这样防御性地设置数据库可以避免很多伤害
但是,如果用户
和组
实体共享大量数据(例如,两者都可以拥有其他对象,具有配置文件页面等),则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列中
- 在应用程序级别,这是典型的继承:一个基本的
用户组和组
,这两个用户组和组
都扩展了该基类/表
- 使用外键仍然可以强制组或用户
- 如果用户或组获得特定的数据,则无需向表中添加对大部分记录无效的列,它可以存储在特定类型的表中
一些缺点:
- 不可能强制一个实体是用户或组,但不能同时是用户或组或不为用户或组(类型较少)
- 除非存储一个冗余列
type
(或is_group
/is_user
),否则确定一个实体是组还是用户需要一个JOIN
,但由于这是在两侧的主键上,开销应该很小
要点:如果您希望将用户和组存储在一个表中,因为它们共享(大多数)特征,这是完全有效的。但是,这意味着从技术上讲,一个组可以是用户的一个成员,而您不能在数据库级别强制执行用户可以在组中,而另一个则不必担心:
表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
)
两个表中的场景:
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
)
如果在应用程序级别出现bug,那么像这样防御性地设置数据库可以避免很多伤害
但是,如果用户
和组
实体共享大量数据(例如,两者都可以拥有其他对象,具有配置文件页面等),则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\u和组,以及user
和