Чи можливо змінити списки 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

... і це спрацювало.

Я зробив щось не так? Це залежить від db двигуна?
Чому всі кажуть, що змінити список ENUM () неможливо? напр. тут http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/


3
У статті, яку ви згадали, не сказано, що це неможливо; в ньому йдеться про те, що зміна списку членів коштує дорого, оскільки двигун виконує повне сканування таблиці.
a1ex07

Я згадував ваше посилання ще в жовтні про ENUMs ( dba.stackexchange.com/a/6966/877 ). Крім того, я розмістив посилання про те, як це зробити в MyISAM ( dba.stackexchange.com/a/6548/877 ). InnoDB не викликає сумнівів у цьому випадку.
RolandoMySQLDBA

Відповіді:


14

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

ENUM, який ви переосмислили у своєму запитанні, насправді зберігав початкові внутрішні значення "так" і "ні", оскільки тестова таблиця востаннє запам'ятала це.

До заселених таблиць відноситься наступне:

Як що до цього?

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

Велика проблема. У заселеній таблиці так, можливо, зараз це можливо. Нові рядки, вставлені з "Так", від'єднуються від попередніх рядків "Так", тому що вони означають, можливо.

ПІДСУМОК

Існують дуже високоризикові методи приманки і перемикання, щоб зробити це дуже швидко в MyISAM . Я б настійно не радив робити це в InnoDB через взаємодію ідентифікатора простору таблиць з ibdata1.


Отже, внутрішньо вони зберігаються як int на основі порядку в ENUM (). Наприклад, ENUM ("так", "ні", "можливо") зберігає внутрішньо 0 для "так", 1 для "ні", 2 для "можливо". Я думаю, що метадані таблиці схожі на ENUM ("так", "ні", "можливо") замість ENUM ("так" => 0, "ні" => 1, "можливо" => 2). Це правда?
Алекс Габі

ENUM - це рядки не цілі числа: dev.mysql.com/doc/refman/5.0/uk/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, доки немає записів із видаленням / зміною значень, інші значення повинні залишатися такими, якими вони є. Єдина перевага полягає в тому, що вона має відновити стіл.
Нуно
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.