【问题标题】:MySQL Database normalizationMySQL 数据库规范化
【发布时间】:2011-12-16 03:32:36
【问题描述】:

我应该实现读取数据库规范化(使用连接表)还是应该将 ENUM 类型用于静态或动态数据?

例如:

我有一张桌子USERuser_status。我应该创建一个表 status 表还是创建一个包含状态的 ENUM 列表?

谢谢大哥

【问题讨论】:

    标签: mysql enums database-normalization


    【解决方案1】:

    恕我直言,枚举扩展使将语义嵌入到表中变得更加容易,并且还通过以下方式提高了效率:

    1. 减少查询所需的连接数
    2. 减少 DBMS 中打开表的数量

    我知道的唯一缺点是

    1. 其他 DBMS 未实现 ENUM 类型
    2. 如果您选择在以后向 ENUM 集添加其他值,则表示您正在应用 DDL 更新 - 对于非常大的表,这可能需要很长时间

    HTH

    C.

    【讨论】:

    • ENUM 还有其他问题。一方面,所有ENUM 列都可以采用空字符串的特殊“未知”值(如果允许,除了NULL);此外,除非使用严格的 SQL 模式,否则此值将用于任何无效值的分配。这可能导致意外的数据库不一致;此外,如果在ENUM 列表中确实有一个明确的空字符串值,这可能会导致巨大的混乱(因为必须检查数值以确定存储的空字符串的“类型”)。
    • 此外,在数字上下文中隐式转换为数值可能会引起相当大的混乱——尤其是当尝试使用表示数字的字符串作为ENUM 值时。该手册提供了一个很好的ENUM 列表('0','1','2') 示例:“如果您存储2,它会被解释为一个索引值,并变为'1'(索引为2 的值)。如果您存储'2',匹配一个枚举值,所以存储为'2',如果存储'3',它不匹配任何枚举值,所以它被当作一个索引,变成'2'(值索引为 3)。"
    • 最后,ENUM 可能会在排序上下文中引起混淆,因为值是根据它们在 ENUM 列表中的位置排序的(而期望值可能会按字典顺序排序)。虽然我不会像 Chris Komlenic 的 8 Reasons Why MySQL's ENUM Data Type Is Evil 那样走得那么远,但我当然认为他的文章值得一读以了解问题;而且,考虑到加入正确索引的表应该比ENUM 更有效(如果不是更有效),我认为这些优势并不那么“真实”。
    • @eggyal:感谢您的链接 - 这很有趣,但似乎有点过时了。关于“未知”值 - 无法在 5.0.22 上复制它 - 只能使值NULL(当表定义允许时)。
    【解决方案2】:

    要考虑的其他东西......

    只能通过修改其他地方的数据库结构来更新枚举,而链接表允许动态创建记录。

    【讨论】:

      【解决方案3】:

      这取决于架构和许多其他因素。

      例如,您不允许读取/写入数据,除非使用存储过程。在这种情况下,您可以随意使用“tinyint”数据类型。如果您允许使用直接查询进行读/写,最好使用约束,即 ENUM 以避免不正确的状态(如果 UI 或后端当然可以放置这种“错误”状态)。

      另一方面(也有可能)数据流可能会发生变化,您可能需要添加新的状态。在这种情况下,您将需要: 1)如果你有静态数据类型,什么也不做; 2) 如果您有 ENUM,请进行更改。

      所以...我的回答是:这取决于您的应用程序和您的要求。

      【讨论】:

      • 您也可以通过外键限制强制执行正确的状态(使用 innodb 表。)
      • ... 并创建另一个表。我认为“过度规范化”(为每个状态添加一个额外的表)通常不是一个好方法。
      • 你能解释一下为什么不吗?有很多桌子根本没有问题。 (并且它们确实允许额外的灵活性,例如向状态添加可编辑的描述,或者为新记录禁用一个描述,同时为旧记录保留它。)
      • 因为他们需要“改变”。小桌子没问题,大桌子就大问题了。
      • 你所说的“改变”是什么意思?创建枚举也需要一个 alter 语句,但也许这不是你的意思?
      猜你喜欢
      • 2013-07-17
      • 1970-01-01
      • 2011-05-18
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 2012-03-08
      相关资源
      最近更新 更多