web-dev-qa-db-ja.com

1つのクエリでMySQL ENUM列の値の名前を変更できますか?

ENUM('value_one','value_two')を含むデータベーステーブルがあるとします。それをENUM('First value','Second value')に変更したいと思います。私は現在次のようにしています:

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

これを行うためのより効率的な方法はありますか? singleALTER TABLEステートメントでこれを実現する方法は?

12
Josh

私があなたに見せようとしている以下のテクニックは鋼の根性を必要とするでしょう。

次の基準が与えられた場合

  • datadirは_/var/lib/mysql_です
  • テーブルは_mydb.mytb_です
  • 呼び出された列挙型列は_enum_col_と呼ばれます
  • エンジンはMyISAM

ここに、死を免れる亀裂があります。

  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. 別のOS/SSHセッションで、.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;_

それでおしまい !!!

警告:私はこのために信用を得ることができません!

この手法は "High Performance MySQL:Optimization、Backups、Replication、and more"、Pages 146-148 under the subheadingSpeeding Up ALTER TABLE。 147ページのパラグラフ1は言う:

これから説明する手法はサポートされておらず、文書化されておらず、機能しない可能性があります。あなたのリスクでそれを使用してください。最初にデータをバックアップすることをお勧めします!

試してみる ! (どうなるか教えてください)

UPDATE 2011-10-05 17:49 EDT

テーブルがMyISAMで、本番環境に十分なスペースがあり、ダウンタイムがまっすぐになる場合は、次のことを試してください。

  1. _service mysql restart --skip-networking_

  2. 別のOS/SSHセッションで、テーブルのコピーを作成します

    • _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.TABLES_は、_mydb.mytbplay_という新しいテーブルの存在を自動的に検出します。

  1. _mydb.mytbplay_でguts-of-steelアルゴリズムを実行する

  2. _mydb.mytbplay_の整合性をテストします

満足したら

  1. _ALTER TABLE mydb.mytb RENAME mydb.mytb_backup;_

  2. _ALTER TABLE mydb.mytbplay RENAME mydb.mytb;_

  3. _service mysql restart_

試してみる!

10
RolandoMySQLDBA

簡単な解決策は次のとおりです。

1-新しい列を追加します。

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

2-列の値をenum2に置き換えてコピーします。

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

3-列columnをドロップし、enumの名前をcolumnに変更します。

[〜#〜] note [〜#〜]:この質問は2011-10-05に戻って、私の解決策はMYSQL 4.1以降で有効(AFAIK)

3
Abdelkader Mh