Mysql 用户设置的数据库设计
在设计用于存储用户设置的表时,下列哪个选项(如果有)被视为最佳做法 (备选方案1) (备选方案2) 为每个设置创建一个新表,例如,通知设置要求您创建:Mysql 用户设置的数据库设计,mysql,sql-server,database,database-design,relational-database,Mysql,Sql Server,Database,Database Design,Relational Database,在设计用于存储用户设置的表时,下列哪个选项(如果有)被视为最佳做法 (备选方案1) (备选方案2) 为每个设置创建一个新表,例如,通知设置要求您创建: "USER_ALERT_SETTINGS" -Id -UserId -EmailAdded (i.e true) -EmailRemoved -PasswordChanged ... ... "USER_EMAIL_SETTINGS" -Id -UserId -EmailLimitMax .... (备选方案3) 每个选项都有其位置,选择取
"USER_ALERT_SETTINGS"
-Id
-UserId
-EmailAdded (i.e true)
-EmailRemoved
-PasswordChanged
...
...
"USER_EMAIL_SETTINGS"
-Id
-UserId
-EmailLimitMax
....
(备选方案3)
每个选项都有其位置,选择取决于您的具体情况。我正在比较下面每个选项的优缺点: 选项1:优点:
- 可以处理很多选择
- 可以轻松添加新选项
- 可以开发一个通用接口来管理选项
- 添加新选项后,使用新选项更新所有用户帐户会更加复杂
- 选项名称可能会失控
- 允许选项值的验证更加复杂,需要额外的元数据
- 每个选项的验证都比选项1容易,因为每个选项都是一个单独的列
- 每个新选项都需要数据库更新
- 有了许多选项,数据库表可能会变得更难使用
- 很难评估“最佳”,因为它取决于您希望运行的查询类型
选项1(通常称为“属性包”、“名称-值对”或“实体-属性-值”或EAV)使存储模式未知的数据变得容易。然而,这使得运行公共关系查询变得很困难,有时甚至不可能。例如,想象一下运行
select count(*)
from USER_ALERT_SETTINGS
where EmailAdded = 1
and Email_LimitMax > 5
这将很快变得非常复杂,特别是因为您的数据库引擎可能无法以有数字意义的方式比较varchar字段(因此“>5”可能无法按您预期的方式工作)
我将计算出您想要运行的查询,并查看哪种设计最支持这些查询。如果您所要做的只是检查单个用户的限制,那么属性包就可以了。如果您必须跨所有用户进行报告,则可能不是这样
JSON或XML也是如此——存储单个记录也可以,但会使查询或报告所有用户变得更加困难。例如,想象一下搜索电子邮件地址的配置设置“bob@domain.com“-这需要搜索所有XML文档以查找节点“电子邮件地址” 选项1(如前所述,“财产袋”)易于实施-很少进行前期分析。但它也有很多缺点
我用过财产袋;但这仅仅是一种逃避,我常常为此感到后悔。我从来没有说过“哎呀,我真希望我把那个明确的专栏变成一个财产袋。”其他答案巧妙地概括了你各种选择的利弊 我相信您的选项1(财产袋)是大多数应用程序的最佳总体设计,特别是如果您针对财产袋的弱点构建了一些保护措施 见以下ERD: 在上述ERD中,
用户设置
表与OP非常相似。不同之处在于,这种设计没有varcharcode
和Value
列,而是有一个FK到设置
表,该表定义了允许的设置(代码)和两个互斥的值列。一个选项是可以接受任何类型用户输入的varchar字段,另一个选项是合法值表的FK
"USER"
-Name
...
-ConfigXML
select count(*)
from USER_ALERT_SETTINGS
where EmailAdded = 1
and Email_LimitMax > 5
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 |
+------+---------+------------+--------------------------+---------------------+
-- 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')
;
-- 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