MySQL ENUM类型与连接表

时间:2008-12-12 06:34:36

标签: mysql database-design enums

我的要求

表格需要维护状态列。

此列代表5个州中的一个。


初步设计

我想我可以将它设为整数列,并使用数值表示状态。

  • 0 =开始
  • 1 =正在运行
  • 2 =坠毁
  • 3 =暂停
  • 4 =已停止

由于我不希望我的应用程序维护从整数到字符串描述的映射,我计划将它们放在一个单独的状态描述表中(依赖于FK关系)。

然后我发现MySQL的ENUM类型完全符合我的要求。 除了直接依赖MySQL之外,使用ENUM类型还有任何陷阱吗?

5 个答案:

答案 0 :(得分:94)

  • 更改ENUM中的值集需要ALTER TABLE,这可能会导致表重组 - 这是一项非常昂贵的操作(如果只是向表中添加一个新值,则不会发生表重组) ENUM定义的结尾,但如果删除一个,或更改顺序,则执行表重组)。而在查找表中更改值集就像INSERT或DELETE一样简单。

  • 无法将其他属性与ENUM中的值相关联,例如哪些属性已停用,哪些属性有资格放入用户界面的下拉列表中。但是,查找表可以包含此类属性的其他列。

  • 查询ENUM以获取不同值的列表非常困难,基本上要求您从INFORMATION_SCHEMA查询数据类型定义,并从返回的BLOB中解析列表。您可以从表中尝试SELECT DISTINCT status,但这只会获取当前正在使用的状态值,这可能不是ENUM中的所有值。但是,如果将值保留在查找表中,则可以轻松查询,排序等。

我不是ENUM的忠实粉丝,你可以说。 : - )

这同样适用于仅将列与固定值集进行比较的CHECK约束。虽然MySQL不支持CHECK约束。

更新:MySQL 8.0.16现在实现了CHECK constraints

答案 1 :(得分:11)

以下是关于speed comparison of enum的文章。也许它提供了一些提示。 恕我直言,它应限于在固定的字符串列表中使用(“是/否”,“儿童/成人”),99%的可能性在将来不会改变。

答案 2 :(得分:7)

mysql中的枚举对于已经解释过的原因是不好的 我可以添加以下事实:Enum不确保在服务器端进行任何类型的验证。如果插入一个值,该行的值不会在枚举定义中退出,则在DB中将获得nice或NULL值,具体取决于枚举字段声明的NULL-ability。

关于tinyints的观点:
- 枚举限制为65535个值
- 如果你不需要超过256个值,tinyint将为每一行占用更少的空间,并且它的行为更加“可预测”。

答案 3 :(得分:3)

如果你的数据库中有大量数据(更多数据,那么你有RAM),你的ENUM值永远不会改变,我会选择ENUM而不是连接。它应该更快。
考虑一下,在连接情况下,您需要在外键上使用索引并在另一个表中使用主键索引。正如Riho所说,请参阅基准。

答案 4 :(得分:-1)

表格更容易国际化。但完全是数据库外的类也是如此。 当这种检查不在业务逻辑中时,很难调试,并且通常不是数据库人员的责任。

作为优化,它可能还为时过早;但OP主要建议将其作为一种便利功能。

另见http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/