Можно ли изменить списки ENUM ()?

19

Я не был уверен, что изменить список ENUM () невозможно, поэтому я сделал тест. В MySQL v5.1.58 я создал тестовую таблицу InnoDB, которая содержит одно поле с именем «bool» типа ENUM («да», «нет»).

Тогда я казнил ...

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
Я упомянул вашу ссылку еще в октябре о ENUM ( dba.stackexchange.com/a/6966/877 ). Кроме того, я разместил ссылку на то, как это сделать, в MyISAM ( dba.stackexchange.com/a/6548/877 ). InnoDB не может быть рассмотрен в этом случае.
RolandoMySQLDBA

Ответы:

14

Пока таблица пуста, проблем нет. Пока новые значения для ENUM добавляются и не переименовываются в заполненной таблице, опять же нет проблем.

ENUM, который вы переопределили в своем вопросе, на самом деле сохранил исходные внутренние значения для yes и no, как это было в прошлой тестовой таблице.

Следующее относится к заполненным таблицам:

Что насчет этого?

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

Теперь у вас есть проблема. Для значений ENUM в полностью заполненной таблице их внутренние значения будут инвертированы, так что теперь да - нет, а нет - да.

Что насчет этого?

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

Большая проблема. В заполненной таблице да, может быть, сейчас. Новые строки, добавленные с помощью yes, отсоединяются от предыдущих строк yes, поскольку теперь они означают «возможно».

РЕЗЮМЕ

В MyISAM есть очень рискованные методы приманки и переключения, которые делают это очень быстро . Я настоятельно рекомендую не делать этого в InnoDB из-за его взаимодействия идентификатора табличного пространства с ibdata1.

RolandoMySQLDBA
источник
Так что внутренне они хранятся как int на основе порядка в ENUM (). Например, ENUM («да», «нет», «возможно») хранит внутренне 0 для «да», 1 для «нет», 2 для «возможно». Я полагаю, что метаданные таблицы похожи на ENUM («да», «нет», «возможно») вместо ENUM («да» => 0, «нет» => 1, «может» => 2). Это правда?
Аалекс Габи
ENUM - это строки, а не целые числа: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA
Я согласен, что ENUM - это строки, но внутренне они не хранятся как строки, не так ли?
Аалекс Габи
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
2
По крайней мере для MariaDB / InnoDB, я могу сказать, что это больше не действует. Изменение середины ENUM, если нет записей со значениями, которые удаляются / изменяются, остальные значения должны оставаться без изменений. Единственным преимуществом является то, что он должен восстановить таблицу.
Нуно