MySQL问题 - 如何处理多种类型的用户 - 一个表还是多个?

时间:2009-06-28 02:21:07

标签: sql mysql database

我正在为具有多个“类型”用户的组织设计数据库。起初,我只创建了一个用户表。但是,虽然所有用户共享一些公共信息(名字,姓氏,用户名,密码等),但每种用户类型都需要一个或两个不适用于所有用户的附加字段。虽然我可以创建这些附加字段并将它们设置为NULL,但我不希望这样做,因为字段是外键并且它对我造成了问题。

这种情况通常如何处理?

谢谢!

4 个答案:

答案 0 :(得分:9)

你没有创建一个包含大量NULLS的大表的直觉就是正确的。从存储/回溯/维护的角度来看,这是一个坏主意,以及数据验证的观点(稍后将详细介绍)。

两种最常见的方法:

1)拥有一个包含所有公共字段的用户表,包括“userType”字段。然后为每个包含额外字段的用户类型提供单独的表。所有用户在users表和一个或多个特定用户类型表中都有一行。这是最常规化和最有效的存储和快速登录。这也允许您使用约束和外键来确保每种用户类型的所有必需信息都可用。

2)拥有一个包含所有公共字段的用户表。有另一个名为 UserAttributes 的表,其中包含userid,key和value字段。特定用户的任何额外元数据都可以存储在此处。这具有不需要任何数据库管理来添加要为每个用户类型存储的新用户类型或元数据的优点。但是,它不允许您在数据库级别进行任何数据验证。

答案 1 :(得分:4)

因此,关系模型不支持“继承”,这可能有助于解决这个问题(尽管一些数据库引擎,例如PostgreSQL,确实支持继承)。

所以,我首先会问自己 - 不同类型的用户是否需要能够出现在同一个环境中,至少在某些情况下?如果是这样,那么你不能只将“共同列”复制并粘贴到多个表中(至少不会影响在这些情况下通过外键到单个表中可以获得的完整性检查)。

第二个问题 - 用户是否 可以持有多个角色?在许多情况下,它会异常,但并非完全不可能,例如员工也可能是供应商或客户。

如果我对这些问题没有得到明确的答案,那么我会设置一个只包含公共字段的用户表;和供应商,员工,beta测试人员,客户以及我可能为用户提供的任何其他类型和角色的单独表格,每个表格都有自己的专用列和用户表上的外键来接收其余的。

我意识到规范化的模式现在已经过时了,但它们已经忠实地为我服务了几十年而且我对它们非常喜欢 - 我只是在需要特定优化时才进行非规范化,并且它发生的次数比想 - !)

这里可能有用的一个有点非规范化的是用户表中的枚举列,表示每个特定用途的“主要”或“唯一”角色(它可以是可以为空的,如果是的话,可能在开始时统一为空从一开始就把它放进去......; - )......但是如果某些特定查询的性能需要它作为特定的优化,我可能会等待添加它,而不是设计那样的架构开始(请注意,这是在您的查询中永远不使用SELECT * FROM的一个关键原因 - 如果您稍后ALTER TABLE添加一列,那么SELECT *就会破坏一个! - 。)

答案 2 :(得分:1)

这是着名的规范化问题。

看看这篇文章或其他类似文章,试图找到符合业务需求的答案。

To normalize or not to normalize

答案 3 :(得分:0)

你没有说你是否使用的是高级语言,所以我只想举例说明类似DB的例子:

数据库设计很难。所以,这将是一个快速而简单的答案。

您的问题是关于数据关系和数据库设计的基本问题。搜索一些基本的操作指南来帮助这个答案。可能有助于考虑如何对信息进行分组,并将“返回”链接到其他集(表)中的主集(表)。

所以,用户就是用户 - 这就是你的桌子。它应包含与用户关联的主要公共元素(列)数据。

然后,另一组信息(例如,权限或其他内容)是另一个表。

只需确保此其他表的值(列)指向它所引用的用户。您可能希望告诉您的数据库在它们之间创建一个“索引”(以提高查找性能等)

,例如,一种用户的“许可”表:

  - integer "id"        <--- unique, index column, auto-increment
  - integer "user_id"   <--- this is which user this belongs
  - ...
  - Boolean "can_write"         <--- example data column
  - Boolean "can_read"          <--- example data column
  - Boolean "can_reboot_system" <--- example data column
  - etc, whatever you want

所以,你可以“SELECT * FROM user_table WHERE first_name ='joe'(或类似)...来获取用户。在那里,我希望你有一些'id'值来识别那一行

现在,只需执行'SELECT * FROM permissions WHERE user_id ='nnnn'(无论该用户的id是什么)。

如果用户只设置了1个权限,那么您可以拥有该user_id,而无需额外的“id”列。