¿Es posible cambiar las listas ENUM ()?

19

No estaba seguro si cambiar la lista ENUM () no es posible, así que hice una prueba. En MySQL v5.1.58 hice una tabla de prueba InnoDB que contiene un campo llamado 'bool' de tipo ENUM ('yes', 'no').

Entonces ejecuté ...

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

...Y funcionó.

¿He hecho algo mal? ¿Depende del motor db?
¿Por qué todos dicen que no es posible cambiar una lista ENUM ()? p.ej. aquí http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Aalex Gabi
fuente
3
El artículo que mencionaste no dice que sea imposible; dice que cambiar la lista de miembros es costoso porque el motor realiza un escaneo completo de la tabla.
a1ex07
Mencioné su enlace en octubre sobre ENUM ( dba.stackexchange.com/a/6966/877 ). Además, publiqué una referencia sobre cómo hacer esto en MyISAM ( dba.stackexchange.com/a/6548/877 ). InnoDB está fuera de discusión en este caso.
RolandoMySQLDBA

Respuestas:

14

Mientras la tabla esté vacía, no hay problema. Siempre y cuando se agreguen nuevos valores para ENUM y no se renombre dado una tabla poblada, nuevamente no hay problema.

El ENUM que redefinió en su pregunta en realidad mantuvo los valores internos originales para sí y no como lo recordó la tabla de prueba por última vez.

Lo siguiente se aplica a las tablas pobladas:

¿Qué hay de esto?

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

Ahora tienes un problema. Los valores ENUM en una tabla completamente poblada tendrían sus valores internos invertidos de modo que sí es ahora no y no es ahora sí.

¿Qué hay de esto?

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

Gran problema. En una tabla poblada, sí es ahora tal vez. Las nuevas filas insertadas con sí se desconectan de las filas anteriores de sí porque ahora significan tal vez.

RESUMEN

Existen técnicas de cambio y cebo de muy alto riesgo para hacer esto muy rápidamente en MyISAM . Recomiendo encarecidamente que no haga esto en InnoDB debido a su interacción de id de tablespace con ibdata1.

RolandoMySQLDBA
fuente
Entonces, internamente, estos se almacenan como int según el orden en ENUM (). Por ejemplo, ENUM ('sí', 'no', 'quizás') almacena internamente 0 para 'sí', 1 para 'no', 2 para 'quizás'. Me imagino que los metadatos de la tabla son como ENUM ('yes', 'no', 'maybe') en lugar de ENUM ('yes' => 0, 'no' => 1, 'maybe' => 2). ¿Es verdad?
Aalex Gabi
ENUM de cadenas no son números enteros: dev.mysql.com/doc/refman/5.0/en/enum.html
RolandoMySQLDBA
Estoy de acuerdo en que los ENUM son cadenas, pero internamente no se almacenan como cadenas, ¿no?
Aalex Gabi
1
Tienes razón en esto. En el enlace que proporcioné, hay una asignación de cadena a entero como metadatos. Busque esta frase: 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.y el mapa de valor / índice está conceptualizado. Por lo tanto, habría un valor ENUM en una tabla asociada con el número de índice interno. Reorganizar las cadenas reorganizará la indexación de metadatos. Esto no es un buen augurio para una tabla poblada al redefinir un ENUM.
RolandoMySQLDBA
2
Al menos para MariaDB / InnoDB, puedo decir que esto ya no es válido. Cambiando el medio de ENUM, siempre que no haya registros con los valores que se eliminan / cambian, los otros valores deben permanecer como están. La única ventaja es que tiene que reconstruir la tabla.
Nuno