【问题标题】:Create another table just to store a few options?创建另一个表只是为了存储一些选项?
【发布时间】:2017-08-11 21:11:49
【问题描述】:

我正在创建一个包含各种表的数据库。让我们以用户表为例。它具有婚姻状况和系统角色等领域。这些字段中的每一个都有预定义的选项。为每个字段创建两个新表是否有意义,因此当将用户添加到系统时,可以进行选择以供选择,例如单身、已婚、离婚?就一个额外的查询而言,这似乎有点矫枉过正。这是最好的方法还是我有其他选择?

【问题讨论】:

  • 能否告诉我们这两个字段的预定义选项是什么?
  • 我还没有决定它们叫什么,但无论如何都不会超过 5 个。

标签: mysql database performance


【解决方案1】:

我肯定会创建单独的表来存储这些不同列的可用选项。就规范化而言,这是一件好事,并且当您需要添加、删除、禁用或更改任何选项时,也可以让您免于烦恼。此外,如果不创建单独的表并直接在用户表中填充值,您最终可能不得不执行select distinct RelationshipStatus from User 之类的操作来获取可用选项,这不如仅选择 10 或许多选项那样高效来自单独表的值。

正如有人评论的那样,过度规范化有时会让人很痛苦,但我发现不规范化某事作为一种快速解决方法几乎总是会再次困扰你。

User
----
ID
RelationshipStatusId
...other columns


RelationshipStatus
------------------
ID
Value
Description

【讨论】:

  • 是的,我同意过度归一化可能不好,但归一化不足通常会带来更多麻烦。
  • 请参考我下面的回答。我想在这种情况下,归一化不足不会给他带来太多麻烦。
  • 是的,我同意额外的表在编写查询时更难处理,但在您的示例中,您正在存储一个代码字符,但随后您提到要将字符映射到像A - Administrator 这样的完整描述。如果您需要从代码字符到这样的描述的映射,我认为单独的表是最好的方法。此外,很难保证您永远不想添加更多代码,然后您必须跟踪所有代码的含义。
  • 不,我不是在映射。很少有像 [M]arried、[D]ivoced 这样的东西不需要对像 Marital Status 这样的列进行任何描述。这很明显。我没有创建任何单独的表格。 DropDowns 将显示全文,但在存储时,如果没有进一步的可能性,他可以存储任何单个字符。如果有任何可能像我在下面的回答中所说的那样,那么你的方法是好的。
【解决方案2】:

您可以在 MySQL 中使用 ENUM 数据类型来更好地处理这种情况。将此类选项存储在单独的表中是一个坏主意,除非您有很多选项..

mysql> DESC Classes;
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | NO   | PRI | NULL    |       |
| dept  | char(4)               | NO   |     | NULL    |       |
| level | enum('Upper','Lower') | NO   |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM Classes;
+----+------+-------+
| id | dept | level |
+----+------+-------+
| 10 | MATH |       |
+----+------+-------+
1 row in set (0.00 sec)

mysql> INSERT INTO Classes VALUES (11, 'ENG', 'Upper')
    -> ;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM Classes;
+----+------+-------+
| id | dept | level |
+----+------+-------+
| 10 | MATH |       |
| 11 | ENG  | Upper |
+----+------+-------+
2 rows in set (0.00 sec)

【讨论】:

  • 因此,如果其中一项需要更改并且我重命名了一个 ENUM 值,那么之前的条目会保留旧值还是足够聪明地更新?它是存储键还是实际值?
  • 如果您要更新行数据,您可以使用简单的更新查询:UPDATE table_name SET field = "value"
  • value 是枚举选项之一
  • 所以 ENUM 基本上只是一种获得一致输入的方法,但该值就像常规值一样存储,对吧?
  • 如果您尝试输入的值不是枚举值之一,则插入操作将成功但该值将为空
【解决方案3】:

出于设计的考虑,请创建另一个具有适当 PK 的表(您不想这样做)。这将具有节省空间的额外好处,因为想象有 10000 个带有“已婚”字样的寄存器。

另外,另一种方法是在您的应用程序中使用“字典”,将其存储在结构和 Id 和值中,如下所示:

Id   Marital Status
 1   Married
 2   Single
 ..  ......

同一张表,但不在数据库中,而是在应用程序中,硬编码、序列化或在外部文件中。

【讨论】:

    【解决方案4】:

    这也取决于行的大小。就速度而言,将表拆分为多个会是更好的选择。 例如。您可以将用户表中的常用列和所有其他信息/可选的列保存在单独的表中。在这种情况下,您在显示数据时也需要小心。

    【讨论】:

      【解决方案5】:

      我想,没有必要过度规范化,因为它会在编写查询时给您带来麻烦。您需要处理太多的连接。

      如果您的婚姻状况的预定义条件是:已婚、单身和离婚,我将只存储一个字符,例如:M、S 和 D,并在 DropDown 中以固定值提供这些选项。

      我认为婚姻状况没有进一步的可能性,除非您想到以下内容:

      想离婚

      已婚但独居。

      对于用户角色,我也会这样做:

      A - 管理员 P - 高级用户 R - 受限用户 G - 客人

      如果您需要更详细的信息,我不会创建更多表格。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-05
        • 1970-01-01
        • 1970-01-01
        • 2017-06-29
        • 1970-01-01
        • 2014-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多