是否可以更改ENUM()列表?


19

我不确定是否无法更改ENUM()列表,所以我进行了测试。在MySQL v5.1.58中,我测试了一个InnoDB表,其中包含一个名为ENUM('yes','no')类型的“ bool”字段。

然后我执行了...

ALTER TABLE  `test`
CHANGE  `bool`  `bool` ENUM(  'yes',  'no',  'maybe' )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL

...而且有效。

我做错了什么吗?它取决于数据库引擎吗?
为什么每个人都说不可能更改ENUM()列表?例如。此处http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/


3
您提到的文章并没有说不可能。它说更改成员列表非常昂贵,因为引擎会进行全表扫描。
a1ex07 2012年

我在十月份提到了您有关ENUM的链接(dba.stackexchange.com/a/6966/877)。此外,我在MyISAM(dba.stackexchange.com/a/6548/877)中发布了有关如何执行此操作的参考。在这种情况下,InnoDB是不可能的。
RolandoMySQLDBA 2012年

Answers:


14

只要表为空,就没有问题。只要添加了ENUM的新值并且在给定填充表的情况下未重命名,就再没有问题。

您在问题中重新定义的ENUM实际上保留了原来的内部值“是”和“否”,因为测试表最后一次记住了它。

以下内容适用于填充的表:

那这个呢?

ALTER TABLE  `test`
CHANGE  `bool`  `bool` ENUM(  'no',  'yes',  'maybe' )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL

现在你有问题了。完全填充的表中的ENUM值将颠倒其内部值,因此yes现在是no,no现在是yes。

那这个呢?

ALTER TABLE  `test`
CHANGE  `bool`  `bool` ENUM(  'maybe', 'no',  'yes' )
CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL

大问题。在填充的表格中,现在可能是。插入yes的新行与以前的yes行断开连接,因为它们现在表示可能是。

摘要

在MyISAM中,有非常高的风险诱饵和切换技术可以非常快地完成此操作。我强烈建议不要在InnoDB中这样做,因为它与ibdata1的表空间ID交互。


因此在内部,根据ENUM()中的顺序将它们存储为int。例如ENUM('yes','no','maybe')在内部存储0表示'yes',1表示'no',2表示'maybe'。我想象表的元数据就像ENUM('yes','no','maybe')而不是ENUM('yes'=> 0,'no'=> 1,'maybe'=> 2)。是真的吗
Aalex Gabi 2012年


我同意ENUM是字符串,但在内部它们也不存储为字符串,不是吗?
Aalex Gabi 2012年

1
你是对的。在我提供的链接中,存在字符串到整数作为元数据的映射。查找此短语:For example, a column specified as ENUM('one', 'two', 'three') can have any of the values shown here. The index of each value is also shown.值/索引映射已概念化。因此,在与内部索引号关联的表中将有一个ENUM值。重新排列字符串将重新排列元数据索引。重新定义ENUM时,这对于填充的表来说不是一个好兆头。
RolandoMySQLDBA 2012年

2
至少对于MariaDB / InnoDB,我可以断定这不再有效。更改ENUM的中间值,只要没有记录被删除/更改的值,其他值就应保持不变。唯一的好处是它必须重建表。
努诺
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.