¿Puedo cambiar el nombre de los valores en una columna ENUM de MySQL en una consulta?


12

Supongamos que tengo una tabla de base de datos con un ENUM('value_one','value_two'). Quiero cambiar eso a un ENUM('First value','Second value'). Actualmente estoy haciendo eso de la siguiente manera:

ALTER TABLE `table` MODIFY `column` ENUM('value_one','value_two','First value','Second value');
UPDATE `table` SET `column`='First Value' WHERE `column`='value_one';
UPDATE `table` SET `column`='Second Value' WHERE `column`='value_two';
ALTER TABLE `table` MODIFY `column` ENUM('First value','Second value');

¿Hay una manera más eficiente de hacer esto, por ejemplo, una manera de lograr esto con una sola ALTER TABLE declaración?

Respuestas:


10

La siguiente técnica que voy a mostrar requerirá agallas de acero.

Dados los siguientes criterios

  • datadir es /var/lib/mysql
  • la mesa es mydb.mytb
  • enum columna llamada se llama enum_col
  • motor es MyISAM

Aquí hay un crack que desafía a la muerte:

  1. CREATE TABLE mydb.mybt LIKE mydb.mytb;

  2. ALTER TABLE mydb.mybt MODIFY enum_col ENUM('First value','Second value');

  3. SET wait_timeout=86400; SET interactive_timeout=86400;

  4. FLUSH TABLES WITH READ LOCK;

  5. En una sesión separada de OS / SSH, intercambie los archivos .frm

    • $ mv /var/lib/mysql/mydb/mytb.frm /var/lib/mysql/mydb/myxx.frm
    • $ mv /var/lib/mysql/mydb/mybt.frm /var/lib/mysql/mydb/mytb.frm
    • $ mv /var/lib/mysql/mydb/myxx.frm /var/lib/mysql/mydb/mybt.frm
  6. UNLOCK TABLES;

  7. DROP TABLE mydb.mybt;

Eso es !!!

CAVEAT: ¡NO PUEDO TOMAR CRÉDITO POR ESTO!

Esta técnica proviene de "MySQL de alto rendimiento: optimización, copias de seguridad, replicación y más", páginas 146-148 bajo el subtítulo Acelerar TABLA ALTER . El párrafo 1 de la página 147 dice:

La técnica que estamos a punto de demostrar es incompatible, indocumentada y puede no funcionar. Úselo bajo su responsabilidad. ¡Le recomendamos que haga una copia de seguridad de sus datos primero!

Darle una oportunidad ! (Por favor, háganos saber cómo resultó)

ACTUALIZACIÓN 2011-10-05 17:49 EDT

Si la tabla es MyISAM y tiene suficiente espacio en producción y una ventana de tiempo de inactividad directa, intente esto:

  1. service mysql restart --skip-networking

  2. En una sesión separada de OS / SSH, haga una copia de la tabla

    • cp /var/lib/mysql/mydb/mytb.frm /var/lib/mysql/mydb/mytbplay.frm
    • cp /var/lib/mysql/mydb/mytb.MYD /var/lib/mysql/mydb/mytbplay.MYD
    • cp /var/lib/mysql/mydb/mytb.MYI /var/lib/mysql/mydb/mytbplay.MYI

INFORMATION_SCHEMA.TABLESdetectará automáticamente la presencia de la nueva tabla llamada mydb.mytbplay.

  1. Realice el algoritmo de tripas de acero en mydb.mytbplay

  2. Usted prueba la integridad de mydb.mytbplay

Si estas satisfecho

  1. ALTER TABLE mydb.mytb RENAME mydb.mytb_backup;

  2. ALTER TABLE mydb.mytbplay RENAME mydb.mytb;

  3. service mysql restart

¡Darle una oportunidad!


¡+1 por una respuesta ingeniosa! Sin embargo, no lo intentaré y le haré saber cómo resultó, ya que la pregunta se refiere a un script de actualización para todas las bases de datos de producción en vivo de mis clientes ;-) Sin embargo, puedo probar esto en un entorno de desarrollo solo por diversión. Pero con esa advertencia, ¡nunca lo ejecutaré en producción!
Josh

3

Una solución simple sería:

1- agrega una nueva columna:

ALTER TABLE `table` ADD `enum2` ENUM('First value', 'Second value') NOT NULL AFTER `enum`;

2- Copie el valor de la columna a enum2 con reemplazos:

UPDATE `table` SET enum2=REPLACE(`column`, "value_one", "new value")

3- Colocar columna column, renombrar enuma column.

NOTA : esta pregunta se remonta al 2011-10-05, mi solución es válida para MYSQL 4.1 y posterior (AFAIK)


Si bien esto parece una buena solución (¡y no tan estresante como la respuesta aceptada!), Vale la pena señalar que el paso 3 requiere al menos una ALTER TABLEdeclaración, y el OP estaba buscando algo que solo requiriera una. Una vez más, dicho esto, parece una solución sólida perfectamente estándar.
RDFozz
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.