MySQLのENUMタイプの列にメンバーを追加するにはどうすればよいですか?


157

MySQLリファレンスマニュアルには、これを行う方法の明確な例はありません。

国を追加する必要がある国名のENUMタイプの列があります。これを達成するための正しいMySQL構文は何ですか?

これが私の試みです:

ALTER TABLE carmake CHANGE country country ENUM('Sweden','Malaysia');

私が得るエラーは: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

country列には、上記の文ではENUM型のカラムです。

作成テーブル出力を表示:

mysql> SHOW CREATE TABLE carmake;
+---------+---------------------------------------------------------------------+
| Table   | Create Table
+---------+---------------------------------------------------------------------+
| carmake | CREATE TABLE `carmake` (
`carmake_id` tinyint(4) NOT NULL AUTO_INCREMENT,
`name` tinytext,
`country` enum('Japan','USA','England','Australia','Germany','France','Italy','Spain','Czech Republic','China','South Korea','India') DEFAULT NULL,
PRIMARY KEY (`carmake_id`),
KEY `name` (`name`(3))
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=latin1 |
+---------+---------------------------------------------------------------------+
1 row in set (0.00 sec)

carmakeの出力から異なる国を選択してください

+----------------+
| country        |
+----------------+
| Italy          |
| Germany        |
| England        |
| USA            |
| France         |
| South Korea    |
| NULL           |
| Australia      |
| Spain          |
| Czech Republic |
+----------------+

回答:


135
ALTER TABLE
    `table_name`
MODIFY COLUMN
    `column_name2` enum(
        'existing_value1',
        'existing_value2',
        'new_value1',
        'new_value2'
    )
NOT NULL AFTER `column_name1`;

7
ほとんどのALTER TABLEコマンドは、テーブル全体を完全に書き換えます。mysqlはenumでそれを行わないほど賢いですか?
ジョン・

enumは、文字列表現を使用した単なる派手な整数です。意味のある古い値を追加するだけなので、最後に項目を追加しても問題ありません。ただし、順序を変更したり、列挙型を削除したりすると、これらの数値は未定義になります。(例:1 =>イタリア、2 =>ドイツ)、拡張は(1 =>イタリア、2 =>ドイツ、3 =>スウェーデン)になります。
lintabá

1
@Johnに依存します。MariaDBの場合、列挙の最後に新しい値を追加できるのinplaceは10.3.7以降です。mariadb.com
Felipe Philipp

99

あなたのコードは私のために働きます。これが私のテストケースです:

mysql> CREATE TABLE carmake (country ENUM('Canada', 'United States'));
Query OK, 0 rows affected (0.00 sec)

mysql> SHOW CREATE TABLE carmake;
+---------+-------------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                            |
+---------+-------------------------------------------------------------------------------------------------------------------------+
| carmake | CREATE TABLE `carmake` (
  `country` enum('Canada','United States') default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+---------+-------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> ALTER TABLE carmake CHANGE country country ENUM('Sweden','Malaysia');
Query OK, 0 rows affected (0.53 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SHOW CREATE TABLE carmake;
+---------+--------------------------------------------------------------------------------------------------------------------+
| Table   | Create Table                                                                                                       |
+---------+--------------------------------------------------------------------------------------------------------------------+
| carmake | CREATE TABLE `carmake` (
  `country` enum('Sweden','Malaysia') default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+---------+--------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

どのエラーが発生していますか?

FWIWこれも機能します:

ALTER TABLE carmake MODIFY COLUMN country ENUM('Sweden','Malaysia');

列挙型の列ではなく、実際に国のテーブルをお勧めします。数百の国があり、かなり大きくて扱いにくい列挙型になります。

編集:今私はあなたのエラーメッセージを見ることができます:

ERROR 1265 (01000): Data truncated for column 'country' at row 1.

お住まいの国の列に、に表示されない値があると思いますENUM。次のコマンドの出力は何ですか?

SELECT DISTINCT country FROM carmake;

別の編集:次のコマンドの出力は何ですか?

SHOW VARIABLES LIKE 'sql_mode';

それはありますSTRICT_TRANS_TABLESSTRICT_ALL_TABLES?この状況では、MySQLが通常の警告を表示するのではなく、エラーが発生する可能性があります。

まだ別の編集:OK、テーブルに新しいにはない値が確実にあることがわかりましたENUM。新しいENUM定義では'Sweden'、およびのみが許可され'Malaysia'ます。テーブルには'USA''India'およびその他いくつかあります。

最終編集(多分):私はあなたがこれをやろうとしていると思います:

ALTER TABLE carmake CHANGE country country ENUM('Italy', 'Germany', 'England', 'USA', 'France', 'South Korea', 'Australia', 'Spain', 'Czech Republic', 'Sweden', 'Malaysia') DEFAULT NULL;

carmakeテーブルに複数の列があります。それはそれと関係がありますか?
Zaid

1
@ザイドはそれを言うことに注意してください。MySQLはENUMカラムへのガベージを許可することで有名です。たとえば、準拠しない値を空の文字列に黙って変換します。問題のある値がないことを100%確信していますか?空の文字列はありませんか?先頭または末尾の空白はありませんか?大文字小文字の違いは?アクセント付きのキャラクター?
Asaph

1
@Zaid更新されたENUM定義にない値がテーブルにあると思います。新しい定義では、スウェーデンとマレーシアのみが許可されます。テーブルには米国、インド、ドイツがあります...これらの値はいずれも新しいENUMでは許可されません。何をやろうとしていることであれば追加 ENUMのオリジナルメンバーを維持しながら、スウェーデン、マレーシア、あなたは再出品する必要がありますすべてのあなたのALTER文で、元のENUM値プラス2つの新しいものを。
Asaph

2
@Zaidどういたしまして。初期に提案したように、ENUMの代わりに外部キーを使用して国テーブルを使用すると、新しい国の行を追加するだけで済みます。ところで、私の提案が役に立ったと思ったら、私の答えを正解としてマークしてください:)
Asaph

3
-1実際の解決策が何であるかが明確でないため。会話が多すぎて、「これを試してみて、代わりにこれを試してみてください」がたくさんあります。最初の応答では、OPの実際の質問に答えることすらありません。問題が何であるかを理解してから、この質問/答えを見つけている人に実際には何の意味もない単純なコードサンプルに入るのです。しばらく経って。編集のコンテキストは一時的なものであり、もはや明確ではありません。
ジムルーベンシュタイン14

73

議論我々は前後にかなり行ってきましたように私はアサフとしていたが従って不明瞭かもしれません。

将来、同様の状況に直面する可能性のある他の人が利益を得るために、私たちの話し合いの結果を明確にすると思います。

ENUMタイプの列は、操作が非常に難しい獣です。ENUMの既存の国のセットに2つの国(マレーシアとスウェーデン)を追加したいと思いました。

MySQL 5.1(私が実行しているもの)は、必要なものに加えて既存のセットを再定義することによってのみENUMを更新できるようです。

これは機能しませんでした:

ALTER TABLE carmake CHANGE country country ENUM('Sweden','Malaysia') DEFAULT NULL;

その理由は、MySQLの文が別のエントリを含む既存のENUMを交換したことだった'Malaysia''Sweden'だけ。MySQLはエラーをスローしました。carmakeテーブルにはすでに次のような値が'England'あり、'USA'それらは新しいものの一部ではないためです。ENUMの定義の。

驚くべきことに、次のことも機能しませんでした。

ALTER TABLE carmake CHANGE country country ENUM('Australia','England','USA'...'Sweden','Malaysia') DEFAULT NULL;

ENUM新しいメンバーを追加する際に、既存の要素の順序も維持する必要があることがわかります。したがって、既存のENUMものがのようENUM('England','USA')に見える場合、新しいものをENUMとして定義する必要がENUM('England','USA','Sweden','Malaysia')ありENUM('USA','England','Sweden','Malaysia')ます。この問題は、既存のテーブルに'USA'またはを使用するレコードがある場合にのみ明らかになり'England'ます。

ボトムライン:

ENUM一度定義したメンバーのセットが変更されない場合にのみ、sを使用します。それ以外の場合、ルックアップテーブルの更新と変更ははるかに簡単です。


私はより強力なボトムラインに挑戦します... "値が決して変化しないという特定のポジティブが100%死んでいるときにのみENUMを使用します"。テーブルが大きくなると、これらの値を変更しなければならない場合に苦痛になります。
DougW 2014

6
その収益に同意するかどうかはわかりません。私を信じて私はENUMがまったく好きではありませんが、可能なENUMに追加することの危険性はわかりません。ENUMは、基本的に、0->オプション1、1->オプション2などのマッピングです。これに追加しても問題は発生しません。
JoshStrange 2015

2
@JoshStrange ENUMの順序が重要な場合(注文に使用する場合など)、それほど危険ではありません。非常に不便になることがあります。
1in9ui5t 2015年

1
一番下の行でそれがMySQLのレガシーバージョンでのみ有効であることを言うことも重要だと思います。なぜなら、私が理解しているのは、新しいバージョンでは問題がないからです。
ニコロ・

この回答はもう関係ありません。以下の回答は承認済みとしてマークする必要があります。
ofirski

17

MYSQLサーバーのバージョン:5.0.27私はこれを試しましたが、あなたのバージョンをチェックインするのにうまくいきました

ALTER TABLE carmake
     MODIFY `country` ENUM('Japan', 'USA', 'England', 'Australia', 'Germany', 'France', 'Italy', 'Spain', 'Czech Republic', 'China', 'South Korea', 'India', 'Sweden', 'Malaysia');

1
なぜこれ以上賛成されないのかわからない。それはシンプルで、私にはうまくいきます。
祖先

1

参考:便利なシミュレーションツール-Wampserver 3.0.6を使用したphpMyAdmin-SQLのプレビュー:「SQLのプレビュー」を使用して、ENUMへの変更で列を保存する前に生成されるSQLコードを確認します。 SQLのプレビュー

上記では、ENUMに「フォード」、「トヨタ」を入力したが、構文エラーを生成している構文ENUM(0)を取得しています。クエリエラー1064#

次に、SQLをコピーして貼り付けて変更し、SQLで実行して、肯定的な結果を得ました。

SQLが変更されました

これは私が頻繁に使用するクイックフィックスであり、変更が必要な既存のENUM値にも使用できます。これは便利かもしれないと思った。


1

ここに別の方法があります...

テーブル「firmas」の「rtipo」列の列挙型定義に「others」を追加します。

set @new_enum = 'others';
set @table_name = 'firmas';
set @column_name = 'rtipo';
select column_type into @tmp from information_schema.columns 
  where table_name = @table_name and column_name=@column_name;
set @tmp = insert(@tmp, instr(@tmp,')'), 0, concat(',\'', @new_enum, '\'') );
set @tmp = concat('alter table ', @table_name, ' modify ', @column_name, ' ', @tmp);
prepare stmt from @tmp;
execute stmt;
deallocate prepare stmt;

-8

信じれば可能です。へへ。このコードを試してください。

public function add_new_enum($new_value)
  {
    $table="product";
    $column="category";
         $row = $this->db->query("SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = ? AND COLUMN_NAME = ?", array($table, $column))->row_array();

    $old_category = array();
    $new_category="";
    foreach (explode(',', str_replace("'", '', substr($row['COLUMN_TYPE'], 5, (strlen($row['COLUMN_TYPE']) - 6)))) as $val)
    {
        //getting the old category first

        $old_category[$val] = $val;
        $new_category.="'".$old_category[$val]."'".",";
    }

     //after the end of foreach, add the $new_value to $new_category

      $new_category.="'".$new_value."'";

    //Then alter the table column with the new enum

    $this->db->query("ALTER TABLE product CHANGE category category ENUM($new_category)");
  }

新しい値を追加する前

新しい値を追加した後


11
これがテーブルに新しいものをもたらす方法はわかりません。質問は純粋にMySQLの観点からもです。あなたの答えは完全に無関係なランダムなPHPを組み込んでおり、あなたはそれを説明しようとはしません。役に立たない情報源
ジョナサン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.