Posso rinominare i valori in una colonna ENUM MySQL in una query?


12

Supponiamo che io abbia una tabella Database con un ENUM('value_one','value_two'). Voglio cambiarlo in un ENUM('First value','Second value'). Attualmente lo sto facendo come segue:

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');

C'è un modo più efficiente per farlo, per esempio un modo per farlo con una sola ALTER TABLE affermazione?

Risposte:


10

La tecnica follolwing che sto per mostrarti richiederà coraggio di acciaio.

Dati i seguenti criteri

  • datadir è /var/lib/mysql
  • la tabella è mydb.mytb
  • viene chiamata la colonna enum chiamata enum_col
  • il motore è MyISAM

Ecco una crepa che sfida la morte:

  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. In una sessione OS / SSH separata, scambiare i file .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;

Questo è tutto !!!

CAVEAT: NON POSSO ACCEDERE A CREDITO PER QUESTO!

Questa tecnica deriva da "MySQL ad alte prestazioni: ottimizzazione, backup, replica e altro", pagine 146-148 nella sottovoce Accelerare la tabella ALTER . Pagina 147 Il paragrafo 1 dice:

La tecnica che stiamo per dimostrare non è supportata, non documentata e potrebbe non funzionare. Usalo a tuo rischio. Ti consigliamo di eseguire prima il backup dei dati!

Provaci ! (Per favore facci sapere come è andata a finire)

AGGIORNAMENTO 2011-10-05 17:49 EDT

Se la tabella è MyISAM e hai abbastanza spazio in produzione e una finestra di downtime diretta, prova questo:

  1. service mysql restart --skip-networking

  2. In una sessione OS / SSH separata, creare una copia della tabella

    • 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.TABLESrileverà automaticamente la presenza della nuova tabella chiamata mydb.mytbplay.

  1. Esegui l'algoritmo guts-of-steel mydb.mytbplay

  2. Si verifica l'integrità di mydb.mytbplay

Se sei soddisfatto

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

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

  3. service mysql restart

Provaci!


+1 per una risposta geniale! Tuttavia, non lo proverò e ti farò sapere come si è rivelato, poiché la domanda si riferisce a uno script di aggiornamento per tutti i database di produzione e live dei miei clienti ;-) Potrei, tuttavia, provarlo su un ambiente di sviluppo solo per divertimento. Ma con questo avvertimento non avrei mai eseguito questo in produzione!
Josh,

3

Una soluzione semplice sarebbe:

1- aggiungi una nuova colonna:

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

2- Copia il valore della colonna in enum2 con sostituzioni:

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

3- Rilascia la colonna column, rinomina enumin column.

NOTA : questa domanda risale al 05-10-2011, la mia soluzione è valida per MYSQL 4.1 e versioni successive (AFAIK)


Anche se questa sembra una buona soluzione (e non tanto snervante quanto la risposta accettata!), Vale la pena notare che il passaggio 3 richiede almeno ALTER TABLEun'affermazione e l'OP stava cercando qualcosa che ne richiedesse solo una. Ancora una volta, detto questo, sembra una soluzione perfettamente standard e solida.
RDFozz,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.