用户设置的数据库设计

001*_*001 41 mysql database sql-server database-design relational-database

在设计用于存储用户设置的表时,以下哪个选项(如果有)被认为是最佳做法?

(选项1)

USER_SETTINGS
-Id
-Code (example "Email_LimitMax")
-Value (example "5")
-UserId
Run Code Online (Sandbox Code Playgroud)

(选项2)

为每个设置创建一个新表,例如,通知设置需要您创建:

"USER_ALERT_SETTINGS"
-Id
-UserId
-EmailAdded (i.e true)
-EmailRemoved 
-PasswordChanged
...
...

"USER_EMAIL_SETTINGS"
-Id
-UserId
-EmailLimitMax
....
Run Code Online (Sandbox Code Playgroud)

(选项3)

"USER"
-Name
...
-ConfigXML
Run Code Online (Sandbox Code Playgroud)

Joe*_*own 74

其他答案已经清楚地概述了各种选择的优缺点.

我相信你的选项1(属性包)是大多数应用程序的最佳整体设计,特别是如果你建立了一些保护措施,以防止打包袋的弱点.

请参阅以下ERD:

物业袋ERD

在上面的ERD中,该USER_SETTING表与OP非常相似.不同之处在于,该设计不是varchar CodeValue列,而是具有SETTING表格的FK,该表格定义了允许的设置(代码)和两个互斥的列.一个选项是varchar字段,可以采用任何类型的用户输入,另一个是FK到合法值表.

SETTING表还有一个标志,指示用户设置是应由FK还是由无约束的varchar输入定义.您还可以添加一个data_typeSETTING告诉系统如何编码和解释USER_SETTING.unconstrained_value.如果您愿意,还可以添加SETTING_GROUP表格以帮助组织用户维护的各种设置.

此设计允许您围绕设置进行表格驱动规则.这样既方便,灵活又易于维护,同时避免了免费使用.


编辑:更多细节,包括一些例子......

请注意,上面的ERD已经增加了更多列详细信息(SETTING上的范围值和ALLOWED_SETTING_VALUE上的列).

以下是一些示例记录.

SETTING:
+----+------------------+-------------+--------------+-----------+-----------+
| id | description      | constrained | data_type    | min_value | max_value |
+----+------------------+-------------+--------------+-----------+-----------+
| 10 | Favourite Colour | true        | alphanumeric | {null}    | {null}    |
| 11 | Item Max Limit   | false       | integer      | 0         | 9001      |
| 12 | Item Min Limit   | false       | integer      | 0         | 9000      |
+----+------------------+-------------+--------------+-----------+-----------+

ALLOWED_SETTING_VALUE:
+-----+------------+--------------+-----------+
| id  | setting_id | item_value   | caption   |
+-----+------------+--------------+-----------+
| 123 | 10         | #0000FF      | Blue      |
| 124 | 10         | #FFFF00      | Yellow    |
| 125 | 10         | #FF00FF      | Pink      |
+-----+------------+--------------+-----------+

USER_SETTING:
+------+---------+------------+--------------------------+---------------------+
| id   | user_id | setting_id | allowed_setting_value_id | unconstrained_value |
+------+---------+------------+--------------------------+---------------------+
| 5678 | 234     | 10         | 124                      | {null}              |
| 7890 | 234     | 11         | {null}                   | 100                 |
| 8901 | 234     | 12         | {null}                   | 1                   |
+------+---------+------------+--------------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

从这些表中,我们可以看到可以确定的一些用户设置是"收藏颜色","项目最大限制"和"项目最小限制".最喜欢的颜色是字母数字的选择列表.项目最小和最大限制是数字,并设置了允许的范围值.该SETTING.constrained列确定用户是从相关的ALLOWED_SETTING_VALUEs 中挑选还是他们是否需要输入USER_SETTING.unconstrained_value.它允许用户与他们的环境中工作的GUI需要了解哪些选项来提供,以及如何加强双方SETTING.data_typemin_valuemax_value限制,如果它们存在.

使用此设计,您可以表格驱动允许的设置,包括足够的元数据,以对用户选择(或输入)的值强制执行一些基本约束/健全性检查.

编辑:示例查询

下面是一些示例SQL,使用上面的数据列出给定用户ID的设置值:

-- DDL and sample data population...
CREATE TABLE SETTING
    (`id` int, `description` varchar(16)
     , `constrained` varchar(5), `data_type` varchar(12)
     , `min_value` varchar(6) NULL , `max_value` varchar(6) NULL)
;

INSERT INTO SETTING
    (`id`, `description`, `constrained`, `data_type`, `min_value`, `max_value`)
VALUES
    (10, 'Favourite Colour', 'true', 'alphanumeric', NULL, NULL),
    (11, 'Item Max Limit', 'false', 'integer', '0', '9001'),
    (12, 'Item Min Limit', 'false', 'integer', '0', '9000')
;

CREATE TABLE ALLOWED_SETTING_VALUE
    (`id` int, `setting_id` int, `item_value` varchar(7)
     , `caption` varchar(6))
;

INSERT INTO ALLOWED_SETTING_VALUE
    (`id`, `setting_id`, `item_value`, `caption`)
VALUES
    (123, 10, '#0000FF', 'Blue'),
    (124, 10, '#FFFF00', 'Yellow'),
    (125, 10, '#FF00FF', 'Pink')
;

CREATE TABLE USER_SETTING
    (`id` int, `user_id` int, `setting_id` int
     , `allowed_setting_value_id` varchar(6) NULL
     , `unconstrained_value` varchar(6) NULL)
;

INSERT INTO USER_SETTING
    (`id`, `user_id`, `setting_id`, `allowed_setting_value_id`, `unconstrained_value`)
VALUES
    (5678, 234, 10, '124', NULL),
    (7890, 234, 11, NULL, '100'),
    (8901, 234, 12, NULL, '1')
;
Run Code Online (Sandbox Code Playgroud)

现在DML提取用户的设置:

-- Show settings for a given user
select
  US.user_id 
, S1.description 
, S1.data_type 
, case when S1.constrained = 'true'
  then AV.item_value
  else US.unconstrained_value
  end value
, AV.caption
from USER_SETTING US
  inner join SETTING S1
    on US.setting_id = S1.id 
  left outer join ALLOWED_SETTING_VALUE AV
    on US.allowed_setting_value_id = AV.id
where US.user_id = 234
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle中看到这个.

  • @YamiOdymel - 我不会.如果你有单一价值的事实(即一次只有一个正确答案),并且如果这些事物在你的系统中具有特殊意义(例如头像,令牌,电子邮件......),那么将这些东西存储为用户的属性(即"USER"表上的列.如果您的应用程序更加结构化,那么使用属性包结构并不是一个好主意. (2认同)
  • @SarvarNishonboev 我将 Visio 与我前段时间创建的 ERD 形状表一起使用,但您可以使用两端带有鱼尾纹“箭头”的通用框和线条。我还使用自定义线条纹理赋予其手绘外观,我发现这在草稿/高级草图中很有用,可以传达它是草图而不是正式设计。 (2认同)

小智 7

选项1(如上所述,"属性包")易于实施 - 前期分析非常少.但它有一堆缺点.

  1. 如果要限制UserSettings.Code的有效值,则需要一个辅助表来显示有效标记的列表.所以你要么(a)没有对UserSettings.Code进行验证 - 你的应用程序代码可以转储任何值,错过捕获错误的机会,或者你必须在新的有效标记列表上添加维护.

  2. UserSettings.Value可能有一个字符串数据类型,以容纳可能进入它的所有不同值.因此,您丢失了真正的数据类型 - 整数,布尔值,浮点数等,以及RDMBS在插入不正确的值时将执行的数据类型检查.再一次,你给自己买了一个潜在的质量保证问题.即使对于字符串值,您也无法约束列的长度.

  3. 您无法根据代码在列上定义DEFAULT值.因此,如果您希望EmailLimitMax默认为5,则无法执行此操作.

  4. 同样,您不能在Values列上放置CHECK约束以防止无效值.

  5. 属性包方法失去了对SQL代码的验证.在命名列方法中,如果Blah不存在,则显示"从UserSettings中选择Blah,其中UserID = x"的查询将获得SQL错误.如果SELECT位于存储过程或视图中,则在代码进入生产之前应用proc/view - way时将出现错误.在属性包方法中,您只需获得NULL.因此,您丢失了数据库提供的另一个自动QA功能,并引入了可能未检测到的错误.

  6. 如上所述,查找条件适用于多个标签的UserID的查询变得更难写 - 它要求对每个被测试的条件加入表.

  7. 不幸的是,Property Bag邀请应用程序开发人员将新代码粘贴到属性包中,而不分析它将如何在其余应用程序中使用.对于大型应用程序,它会成为"隐藏"属性的来源,因为它们没有正式建模.这就像使用纯标记值而不是命名属性来创建对象模型:它提供了一个转义阀,但是您缺少编译器为强类型命名属性提供的所有帮助.或者像没有模式验证的生产XML一样.

  8. 列名方法是自我记录的.表中的列列表告诉任何开发人员可能的用户设置.

我用过物业袋; 但只是作为一个逃生阀我经常后悔.我从来没有说过"哎呀,我希望我把这个明确的专栏作为财产包."

  • 您会推荐什么? (2认同)

Saj*_*ith 7

考虑这个简单的例子。

如果您有2个表,则UserTable(包含用户详细信息)和 SettingsTable(包含设置详细信息)。然后创建一个新的表UserSettings来关联UserTable和SettingsTable,如下所示

用户设置数据库设计

希望您能从此示例中找到正确的解决方案。

  • 这是一个很好的答案。也许允许多种数据类型应该稍微复杂一点。 (2认同)

Ste*_*oke 5

每个选项都有它的位置,选择取决于您的具体情况。我正在比较以下每个选项的优缺点:

选项 1:优点:

  • 可以处理多种选择
  • 可以轻松添加新选项
  • 可以开发通用接口来管理选项

选项 1:缺点

  • 添加新选项后,使用新选项更新所有用户帐户会更加复杂
  • 选项名称可能会失控
  • 允许选项值的验证更复杂,为此需要额外的元数据

选项 2:优点

  • 每个选项的验证比选项 1 更容易,因为每个选项都是一个单独的列

选项 2:缺点

  • 每个新选项都需要更新数据库
  • 有许多选项,数据库表可能变得更难使用

  • 或者,配置可以作为 JSON, XML 存储在数据库中,您对此有何看法? (3认同)