Czy mogę zmienić nazwę wartości w kolumnie MySQL ENUM w jednym zapytaniu?

12

Załóżmy, że mam tabelę bazy danych z ENUM('value_one','value_two'). Chcę to zmienić na ENUM('First value','Second value'). Obecnie robię to w następujący sposób:

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

Czy istnieje bardziej skuteczny sposób, aby to zrobić, np. Sposób, aby to osiągnąć za pomocą pojedynczej ALTER TABLE instrukcji?

Josh
źródło

Odpowiedzi:

10

Technika podążania, którą zamierzam pokazać, będzie wymagała wnętrzności ze stali.

Biorąc pod uwagę następujące kryteria

  • datadir jest /var/lib/mysql
  • stół jest mydb.mytb
  • Wywoływana jest kolumna wyliczeniowa enum_col
  • silnik to MyISAM

Oto śmiertelnie niebezpieczny trzask:

  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. W osobnej sesji OS / SSH zamień pliki .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;

Otóż ​​to !!!

PRZESTROGA: NIE MOŻNA PODJĘĆ KREDYTU ZA TO!

Ta technika pochodzi z „High Performance MySQL: Optymalizacja, kopie zapasowe, replikacja i więcej”, strony 146–148 w podtytule Przyspieszenie ALTER TABELI . Page 147 Ustęp 1 mówi:

Technika, którą zamierzamy zademonstrować, jest nieobsługiwana, nieudokumentowana i może nie działać. Użyj go na własne ryzyko. Radzimy najpierw wykonać kopię zapasową danych!

Spróbuj ! (Daj nam znać, jak się okazało)

AKTUALIZACJA 2011-10-05 17:49 EDT

Jeśli tabelą jest MyISAM i masz wystarczająco dużo miejsca na produkcji oraz proste okno przestoju, spróbuj tego:

  1. service mysql restart --skip-networking

  2. W osobnej sesji OS / SSH wykonaj kopię tabeli

    • 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.TABLESautomatycznie wykryje obecność nowej tabeli o nazwie mydb.mytbplay.

  1. Wykonaj algorytm odwagi mydb.mytbplay

  2. Testujesz integralność mydb.mytbplay

Jeśli jesteś zadowolony

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

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

  3. service mysql restart

Spróbuj!

RolandoMySQLDBA
źródło
+1 za genialną odpowiedź! Nie będę jednak próbował tego i informuję, jak się to potoczyło, ponieważ pytanie dotyczy skryptu aktualizacji dla wszystkich rzeczywistych, produkcyjnych baz danych mojego klienta ;-) Mogę jednak wypróbować to w środowisku programistycznym dla zabawy. Ale z tym ostrzeżeniem nigdy nie uruchomię tego w produkcji!
Josh
3

Prostym rozwiązaniem byłoby:

1- dodaj nową kolumnę:

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

2- Skopiuj wartość kolumny do enum2 z zamiennikami:

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

3- Upuść kolumnę column, zmień nazwę enumna column.

UWAGA : to pytanie z powrotem do 2011-10-05, moje rozwiązanie jest ważne dla MYSQL 4.1 i nowszych (AFAIK)

Abdelkader Mh
źródło
Chociaż brzmi to jak dobre rozwiązanie (i nie tak nerwowe jak zaakceptowana odpowiedź!), Warto zauważyć, że krok 3 wymaga co najmniej jednego ALTER TABLEoświadczenia, a OP szukał czegoś, co wymagało tylko jednego. To powiedziawszy, wydaje się, że jest to całkowicie standardowe, solidne rozwiązanie.
RDFozz