问题 Mysql数据类型 - Enum或不枚举,Enum是否为空?


我有大型数据库(数百万行),我正在尝试为2个字段的数据类型做出最佳选择。我做的大部分都是varchar或INT。然而,2个领域我想知道Enum是否是最好的方式。

领域1 第一个字段是性别,我的数据目前是“男性”或“女性”,或者可能是 空白。我最初设置如下:

GENDER VARCHAR(6) NOT NULL

这是最好的方式,还是最好将其设置为:

GENDER ENUM ('Male', 'Female') NOT NULL

我是否需要将其设为非空以允许空白,或者我是否需要添加空白,即

GENDER ENUM ('Male', 'Female', '') NOT NULL

更不用说了,我正在考虑将整个领域转换为M或F.

领域2: 我有几乎相同的事情需要考虑,除了状态字段,可能包括52个值(50个状态,DC,加上空白)。

我想最大的问题是 - 所有这些Enum的东西都值得吗?我的数据库有数百万行,所以一切都是一个因素,但我应该只使用VARCHAR(2)作为状态而不是ENUM。


6017
2017-10-05 21:05


起源



答案:


我经常适用于这种情况的经验法则是不使用MySQL ENUM。使用它们会产生维护问题,尤其是在添加/删除/重命名某些值时。在InnoDB中,重命名和删除枚举值在大表上很重要。不添加值(只要您不在中间添加它)。

由于您可能希望将此列保留在上下文中,并且不允许任何值超出此上下文,因此IMHO最好使用INT,并将其作为外键连接到值表(列id,值)。

您可以轻松地在此表中添加和重命名值,在删除值之前,FK将强制处理主表中具有此值的任何现有记录。

要轻松读取数据,您只需要一个简单的JOIN即可。

注意:由于性别是最终的,你可能想把它保留为VARCHAR(1)或使用像Johan建议的ENUM,但谁知道呢?您可能希望将来支持跨性别者和双性化。不开玩笑。


10
2017-10-05 21:24



通常我同意,但对于性别2,也许3个绝对最大7个值,我认为它是矫枉过正。 - Johan
@Johan:7对于我的外星人太空战斗游戏来说是一个非常小的数字。 - ypercubeᵀᴹ
除了笑话, CHAR(1) 是一种有效的方法。它甚至允许你将一个外键添加到一个引用表(无论是2,3,7行),你不必乱用它 ENUM当你需要添加一个新的性别(或一个 'Unknown' 值)。 - ypercubeᵀᴹ
我担心的一件事是将来导入CSV文件。我不想遇到可能会中断导入的空白字段的问题。 - Kevin
@ypercube,几乎睡觉了,我该怎么办 那 我头脑中的照片? - Johan


答案:


我经常适用于这种情况的经验法则是不使用MySQL ENUM。使用它们会产生维护问题,尤其是在添加/删除/重命名某些值时。在InnoDB中,重命名和删除枚举值在大表上很重要。不添加值(只要您不在中间添加它)。

由于您可能希望将此列保留在上下文中,并且不允许任何值超出此上下文,因此IMHO最好使用INT,并将其作为外键连接到值表(列id,值)。

您可以轻松地在此表中添加和重命名值,在删除值之前,FK将强制处理主表中具有此值的任何现有记录。

要轻松读取数据,您只需要一个简单的JOIN即可。

注意:由于性别是最终的,你可能想把它保留为VARCHAR(1)或使用像Johan建议的ENUM,但谁知道呢?您可能希望将来支持跨性别者和双性化。不开玩笑。


10
2017-10-05 21:24



通常我同意,但对于性别2,也许3个绝对最大7个值,我认为它是矫枉过正。 - Johan
@Johan:7对于我的外星人太空战斗游戏来说是一个非常小的数字。 - ypercubeᵀᴹ
除了笑话, CHAR(1) 是一种有效的方法。它甚至允许你将一个外键添加到一个引用表(无论是2,3,7行),你不必乱用它 ENUM当你需要添加一个新的性别(或一个 'Unknown' 值)。 - ypercubeᵀᴹ
我担心的一件事是将来导入CSV文件。我不想遇到可能会中断导入的空白字段的问题。 - Kevin
@ypercube,几乎睡觉了,我该怎么办 那 我头脑中的照片? - Johan


如果你想拥有一个值 no value entered, 使用 null 那是什么 null 是专为!

如果你想在男性和女性之间指定一些东西(一些不幸的人有这种情况),请使用

ENUM('male','female','neither') NULL;

请注意,枚举确实如此  将文字文本值存储在列中。
male 存储为1, female 作为2和 neither 如3等
这意味着它比varchar更有效。

如果你正在努力 null 在您的选择中,请注意您可以使用 ifnull 要么 coalesce 功能来取代 null 用更有用的东西。

SELECT IFNULL(gender,'unknown') as gender FROM people;
-- or the identical statement
SELECT COALESCE(gender,'unknown') as gender FROM people;

6
2017-10-05 21:28



+1正确使用NULL和相关函数示例。 - Galz