Bagaimana cara menambahkan lebih banyak anggota ke kolom tipe ENUM di MySQL?

157

Manual referensi MySQL tidak memberikan contoh yang jelas tentang cara melakukan ini.

Saya memiliki kolom ENUM nama negara yang harus saya tambahkan lebih banyak negara. Apa sintaks MySQL yang benar untuk mencapai ini?

Inilah usaha saya:

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

Kesalahan yang saya dapatkan adalah: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

The countrykolom kolom ENUM-jenis di atas-pernyataan.

MENUNJUKKAN OUTPUT TABEL :

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)

PILIH negara berbeda DARI OUTPUT carmake :

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

Jawaban:

135
ALTER TABLE
    `table_name`
MODIFY COLUMN
    `column_name2` enum(
        'existing_value1',
        'existing_value2',
        'new_value1',
        'new_value2'
    )
NOT NULL AFTER `column_name1`;
Pradip Chongbang
sumber
7
Sebagian besar perintah ALTER TABLE akan sepenuhnya menulis ulang seluruh tabel. Apakah mysql cukup pintar untuk tidak melakukan itu dengan enum?
Yohanes
enum hanyalah bilangan bulat mewah, dengan representasi string. menambahkan item pada bagian akhir tidak masalah, karena Anda baru saja menambahkan makna nilai lama. tetapi mengubah urutan / menghapus enum akan membuat angka-angka itu tidak terdefinisi. (mis. 1 => italia, 2 => jerman), maka perpanjangannya adalah (1 => italia, 2 => jerman, 3 => sweenden).
lintabá
1
@ John tergantung. Untuk MariaDB, menambahkan nilai baru di akhir enum dapat dilakukan inplacesejak 10.3.7: mariadb.com/kb/en/library/…
Felipe Philipp
99

Kode Anda berfungsi untuk saya. Ini adalah test case saya:

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)

Kesalahan apa yang Anda lihat?

FWIW ini juga akan berfungsi:

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

Saya benar-benar akan merekomendasikan tabel negara daripada kolom enum. Anda mungkin memiliki ratusan negara yang akan menghasilkan enum yang agak besar dan canggung.

EDIT: Sekarang saya bisa melihat pesan kesalahan Anda:

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

Saya menduga Anda memiliki beberapa nilai di kolom negara Anda yang tidak muncul di ENUM. Apa output dari perintah berikut?

SELECT DISTINCT country FROM carmake;

EDIT LAIN: Apa output dari perintah berikut?

SHOW VARIABLES LIKE 'sql_mode';

Apakah itu STRICT_TRANS_TABLESatau STRICT_ALL_TABLES? Itu bisa menyebabkan kesalahan, daripada peringatan yang biasa diberikan MySQL pada Anda dalam situasi ini.

TETAPI EDIT LAIN: Ok, sekarang saya melihat bahwa Anda pasti memiliki nilai di tabel yang tidak ada di yang baru ENUM. ENUMDefinisi baru hanya memungkinkan 'Sweden'dan 'Malaysia'. Meja telah 'USA', 'India'dan beberapa lainnya.

EDIT TERAKHIR (MAYBE): Saya pikir Anda mencoba melakukan ini:

ALTER TABLE carmake CHANGE country country ENUM('Italy', 'Germany', 'England', 'USA', 'France', 'South Korea', 'Australia', 'Spain', 'Czech Republic', 'Sweden', 'Malaysia') DEFAULT NULL;
Asaf
sumber
Ada lebih dari satu kolom di carmakemeja saya . Mungkinkah itu ada hubungannya dengan itu?
Zaid
1
@ Zaid berhati-hatilah mengatakan itu. MySQL terkenal karena membiarkan sampah masuk ke kolom ENUM. Ini akan secara diam-diam mengkonversi nilai yang tidak sesuai ke string kosong, misalnya. Apakah Anda 100% yakin tidak memiliki nilai yang menyinggung? Tidak ada string kosong? Tidak ada spasi putih terdepan atau tambahan? Perbedaan kasus? Karakter beraksen?
Asaf
1
@Zaid Saya pikir Anda memiliki nilai di tabel Anda yang tidak ada dari definisi ENUM Anda yang diperbarui. Definisi baru Anda hanya mengizinkan Swedia dan Malaysia. Meja Anda memiliki AS, India, Jerman ... Tidak satu pun dari nilai-nilai itu akan diizinkan di ENUM baru Anda. Jika yang ingin Anda lakukan adalah menambahkan Swedia dan Malaysia sambil mempertahankan anggota asli ENUM, Anda harus mencatat kembali semua nilai ENUM asli ditambah 2 yang baru dalam pernyataan ALTER Anda.
Asaph
2
@Zaid Sama-sama. Jika Anda menggunakan tabel negara dengan kunci asing alih-alih ENUM seperti yang saya sarankan sejak awal, Anda dapat dengan mudah menambahkan baris untuk negara baru. BTW: Jika Anda telah menemukan saran saya bermanfaat, tandai jawaban saya benar :)
Asaf
3
-1 Karena tidak ada kejelasan tentang apa solusi sebenarnya di sini. Ada terlalu banyak percakapan dan banyak "coba ini, oh coba ini juga." Respons awal bahkan tidak menjawab pertanyaan aktual OP - tidak sampai nanti Anda menyadari masalahnya, dan kemudian Anda masuk ke sampel kode sederhana yang tidak benar-benar berarti bagi seseorang yang menemukan pertanyaan / jawaban ini di kemudian hari. Konteks pengeditan Anda bersifat sementara, dan tidak lagi jelas.
Jim Rubenstein
73

The diskusi saya dengan Asaf mungkin tidak jelas untuk mengikuti saat kami pergi bolak-balik sedikit.

Saya berpikir bahwa saya dapat mengklarifikasi hasil dari wacana kami untuk orang lain yang mungkin menghadapi situasi serupa di masa depan untuk mendapat manfaat dari:

ENUM-tipe kolom adalah binatang yang sangat sulit untuk dimanipulasi. Saya ingin menambahkan dua negara (Malaysia & Swedia) ke set negara yang ada di ENUM saya.

Tampaknya MySQL 5.1 (yang sedang saya jalankan) hanya dapat memperbarui ENUM dengan mendefinisikan ulang set yang ada di samping apa yang saya inginkan:

Ini tidak berhasil:

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

Alasannya adalah bahwa pernyataan MySQL mengganti ENUM yang ada dengan yang lain yang berisi entri 'Malaysia'dan 'Sweden'hanya. MySQL memunculkan kesalahan karena carmaketabel sudah memiliki nilai suka 'England'dan 'USA'yang bukan bagian dari ENUMdefinisi baru.

Yang mengejutkan, yang berikut ini juga tidak berfungsi:

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

Ternyata bahkan urutan elemen yang ada ENUMperlu dipertahankan sambil menambahkan anggota baru ke dalamnya. Jadi jika yang saya miliki ENUMterlihat seperti ENUM('England','USA'), maka yang baru ENUMharus didefinisikan sebagai ENUM('England','USA','Sweden','Malaysia')tidak ENUM('USA','England','Sweden','Malaysia'). Masalah ini hanya menjadi manifes ketika ada catatan di tabel yang ada yang menggunakan 'USA'atau 'England'nilai.

BOTTOM LINE:

Hanya gunakan ENUMketika Anda tidak mengharapkan set anggota Anda berubah setelah ditentukan. Jika tidak, tabel pencarian jauh lebih mudah untuk diperbarui dan dimodifikasi.

Zaid
sumber
Saya akan berani garis bawah yang lebih kuat ... "hanya menggunakan ENUM ketika Anda 100% mati yakin positif bahwa nilai-nilai tidak akan pernah berubah". Jika sebuah tabel tumbuh besar, akan sangat menyebalkan jika Anda harus mengubah nilai-nilai itu.
DougW
6
Saya tidak yakin saya setuju dengan intinya. Percayalah, saya tidak suka ENUM sama sekali, tetapi saya tidak melihat bahayanya MENAMBAH ENUM yang mungkin. ENUM adalah, pada intinya, pemetaan 0 -> Opsi 1, 1-> Opsi 2, dll. Menambahkan ke yang seharusnya tidak menyebabkan masalah.
JoshStrange
2
@ JoshStrange Ini bukan bahaya, itu bisa menjadi ketidaknyamanan yang sangat besar ketika urutan ENUM Anda penting (misalnya, ketika digunakan untuk memesan).
1in9ui5t
1
Saya pikir penting juga untuk mengatakan bahwa ini hanya valid dengan versi lama MySQL karena untuk apa yang saya mengerti, dengan yang lebih baru tidak ada masalah.
Niccolò
Jawaban ini tidak relevan lagi, yang di bawah ini harus ditandai sebagai diterima.
ofirski
17

Dalam versi server MYSQL: 5.0.27 saya mencoba ini dan itu berfungsi dengan baik bagi saya memeriksa versi Anda

ALTER TABLE carmake
     MODIFY `country` ENUM('Japan', 'USA', 'England', 'Australia', 'Germany', 'France', 'Italy', 'Spain', 'Czech Republic', 'China', 'South Korea', 'India', 'Sweden', 'Malaysia');
Abhishek
sumber
1
Tidak yakin mengapa ini tidak lebih dipilih. Sederhana, dan itu bekerja untuk saya.
leluhur
1

FYI: Alat simulasi yang berguna - phpMyAdmin dengan Wampserver 3.0.6 - Pratinjau SQL: Saya menggunakan 'Pratinjau SQL' untuk melihat kode SQL yang akan dihasilkan sebelum Anda menyimpan kolom dengan perubahan ke ENUM. Pratinjau SQL

Di atas Anda melihat bahwa saya telah memasukkan 'Ford', 'Toyota' ke dalam ENUM tetapi saya mendapatkan sintaks ENUM (0) yang menghasilkan kesalahan sintaks Query error 1064 #

Saya kemudian salin dan tempel dan ubah SQL dan jalankan melalui SQL dengan hasil positif.

SQL berubah

Ini adalah perbaikan cepat yang sering saya gunakan dan juga dapat digunakan pada nilai ENUM yang ada yang perlu diubah. Kupikir ini mungkin berguna.

Addi
sumber
1

Ini cara lain ...

Ini menambahkan "orang lain" ke definisi enum dari kolom "rtipo" dari tabel "firmas".

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;
Antonio
sumber
-8

Itu mungkin jika Anda percaya. Hehe. coba kode ini.

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)");
  }

Sebelum menambahkan nilai baru

Setelah menambahkan nilai baru

Alj
sumber
11
Saya tidak melihat bagaimana ini membawa sesuatu yang baru ke meja. Pertanyaannya adalah murni dari sudut pandang MySQL juga. Jawaban Anda mencakup PHP acak yang sama sekali tidak relevan dan Anda tidak berusaha menjelaskannya. Sumber daya informasi yang tidak berguna
Jonathan