ฉันจะเพิ่มสมาชิกในคอลัมน์ประเภท ENUM ของฉันใน MySQL ได้อย่างไร


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)

เลือก DISTINCT country จาก carmake OUTPUT:

+----------------+
| 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 => Sweenden)
lintabá

1
@John ขึ้น สำหรับ MariaDB การเพิ่มค่าใหม่ในตอนท้ายของ enum สามารถทำได้inplaceตั้งแต่ 10.3.7: mariadb.com/kb/en/library/…
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');

ฉันอยากจะแนะนำตารางประเทศแทนคอลัมน์ enum คุณอาจมีหลายร้อยประเทศที่จะทำเงินได้ค่อนข้างใหญ่และอึดอัดใจ

แก้ไข: ตอนนี้ฉันเห็นข้อความผิดพลาดของคุณแล้ว:

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

ENUMฉันสงสัยว่าคุณมีค่าบางอย่างในประเทศของคอลัมน์ที่ไม่ปรากฏใน ผลลัพธ์ของคำสั่งต่อไปนี้คืออะไร?

SELECT DISTINCT country FROM carmake;

แก้ไขอีกอัน: ผลลัพธ์ของคำสั่งต่อไปนี้คืออะไร?

SHOW VARIABLES LIKE 'sql_mode';

มันเป็นSTRICT_TRANS_TABLESหรือSTRICT_ALL_TABLES? ที่อาจนำไปสู่ข้อผิดพลาดแทนที่จะใช้คำเตือน MySQL ปกติจะให้คุณในสถานการณ์นี้

อีกแก้ไข: ENUMตกลงตอนนี้ผมเห็นว่าคุณแน่นอนมีค่าในตารางที่ไม่ได้อยู่ในใหม่ ใหม่ENUMความหมายเพียง แต่ช่วยให้และ'Sweden' 'Malaysia'ตารางมี'USA', 'India'และอื่น ๆ หลาย

แก้ไขล่าสุด (MAYBE): ฉันคิดว่าคุณกำลังพยายามทำสิ่งนี้:

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
@ Zaid ระวังที่จะพูดอย่างนั้น MySQL นั้นมีชื่อเสียงในการทิ้งขยะลงในคอลัมน์ ENUM มันจะแปลงค่าที่ไม่เป็นไปตามความเงียบเป็นสตริงว่างตัวอย่างเช่น คุณแน่ใจ 100% ว่าคุณไม่มีค่าผิดหรือไม่? ไม่มีสตริงว่างเปล่า? ไม่มีช่องว่างนำหน้าหรือต่อท้าย? ความแตกต่างของกรณี? อักขระเน้นเสียง?
Asaph

1
@ Zaid ฉันคิดว่าคุณมีค่าในตารางที่ไม่อยู่ในนิยาม ENUM ที่อัปเดตของคุณ คำจำกัดความใหม่ของคุณอนุญาตเฉพาะสวีเดนและมาเลเซีย ตารางของคุณมี USA, อินเดีย, เยอรมนี ... ไม่มีค่าใดที่จะอนุญาตใน ENUM ใหม่ของคุณ หากสิ่งที่คุณกำลังพยายามที่จะทำคือการเพิ่มสวีเดนและมาเลเซียขณะที่รักษาสมาชิกเดิมของ ENUM คุณจะต้อง relist ทุกค่า ENUM เดิมแถม 2 ใหม่ในงบการเปลี่ยนแปลงของคุณ
Asaph

2
@ Zaid คุณยินดีต้อนรับ หากคุณใช้ตารางประเทศที่มีคีย์ต่างประเทศแทน ENUM ตามที่ฉันแนะนำไว้ก่อนหน้านี้คุณจะสามารถเพิ่มแถวสำหรับประเทศใหม่ได้ BTW: หากคุณพบว่าข้อเสนอแนะของฉันที่เป็นประโยชน์โปรดทำเครื่องหมายคำตอบของฉันที่ถูกต้อง :)
อาสาฟ

3
-1 สำหรับการขาดความชัดเจนในสิ่งที่เป็นทางออกที่แท้จริงที่นี่ มีการสนทนามากเกินไปและ "ลองทำอย่างนี้ดีลองแทนนี่สิ" การตอบสนองครั้งแรกไม่ได้ตอบคำถามจริงของ OP แต่ก็ไม่ได้จนกว่าคุณจะรู้ว่าปัญหาคืออะไรและจากนั้นคุณจะเข้าสู่ตัวอย่างโค้ดง่ายๆที่ไม่ได้มีความหมายอะไรกับคนที่กำลังค้นหาคำถาม / คำตอบนี้ ในเวลาต่อมา บริบทของการแก้ไขของคุณคือ / เป็นชั่วคราวและไม่ชัดเจนอีกต่อไป
Jim Rubenstein

73

การสนทนาที่ฉันมีกับ Asaph อาจไม่ชัดเจนที่จะติดตามในขณะที่เราเดินกลับไปกลับมา

ฉันคิดว่าฉันอาจอธิบายผลการวิพากษ์วิจารณ์ของเราสำหรับผู้อื่นที่อาจเผชิญสถานการณ์ที่คล้ายคลึงกันในอนาคตเพื่อรับประโยชน์จาก:

ENUM- คอลัมน์ประเภทเป็นสัตว์ที่ยากมากที่จะจัดการ ฉันต้องการเพิ่มสองประเทศ (มาเลเซียและสวีเดน) ลงในกลุ่มประเทศที่มีอยู่ใน ENUM ของฉัน

ดูเหมือนว่า 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เมื่อคุณไม่ได้คาดหวังว่าชุดสมาชิกของคุณจะเปลี่ยนเมื่อกำหนดไว้ มิฉะนั้นตารางการค้นหาจะง่ายต่อการอัพเดทและแก้ไข


ฉันจะเอากำไรที่ดีกว่า ... "ใช้เฉพาะ ENUM เมื่อคุณตายไป 100% แน่นอนว่าค่าจะไม่เปลี่ยนแปลง" หากโต๊ะโตขึ้นมันจะเจ็บปวดถ้าคุณต้องเปลี่ยนค่าเหล่านั้น
DougW

6
ฉันไม่แน่ใจว่าฉันเห็นด้วยกับที่บรรทัดล่าง เชื่อใจฉันฉันไม่ชอบ ENUM เลย แต่ฉันไม่เห็นอันตรายในการเพิ่ม ENUM ที่เป็นไปได้ ENUM คือการทำแผนที่เป็น 0 -> ตัวเลือก 1, 1-> ตัวเลือก 2 เป็นต้นการเพิ่มลงในนั้นไม่ควรทำให้เกิดปัญหา
JoshStrange

2
@JoshStrange มันไม่ได้อันตรายอะไรมากมันอาจเป็นความไม่สะดวกอย่างมากเมื่อคำสั่งของ ENUM ของคุณมีความสำคัญ (เช่นเมื่อใช้สำหรับการสั่งซื้อ)
1in9ui5t

1
ฉันคิดว่าเป็นสิ่งสำคัญที่จะพูดในบรรทัดล่างที่ใช้ได้เฉพาะกับ MySQL รุ่นเก่าเพราะสิ่งที่ฉันเข้าใจกับสิ่งใหม่ ๆ ไม่มีปัญหา
Niccolò

คำตอบนี้ไม่เกี่ยวข้องอีกต่อไปคำตอบด้านล่างควรทำเครื่องหมายว่ายอมรับ
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

FYI: เครื่องมือจำลองที่มีประโยชน์ - phpMyAdmin พร้อม Wampserver 3.0.6 - ดูตัวอย่าง SQL: ฉันใช้ 'Preview SQL' เพื่อดูรหัส SQL ที่จะสร้างขึ้นก่อนที่คุณจะบันทึกคอลัมน์โดยเปลี่ยนเป็น ENUM ดูตัวอย่าง SQL

ด้านบนคุณจะเห็นว่าฉันได้ป้อน 'ฟอร์ด', 'โตโยต้า' ลงใน ENUM แต่ฉันได้รับไวยากรณ์ ENUM (0) ซึ่งกำลังสร้างข้อผิดพลาดทางไวยากรณ์Query error 1064 #

จากนั้นฉันก็คัดลอกและวางและแก้ไข SQL และรันผ่าน SQL ด้วยผลลัพธ์ที่เป็นบวก

เปลี่ยน SQL แล้ว

นี่เป็นคำแนะนำด่วนที่ฉันใช้บ่อยและยังสามารถใช้กับค่า ENUM ที่มีอยู่ที่ต้องแก้ไข คิดว่านี่อาจเป็นประโยชน์


1

นี่เป็นอีกวิธีหนึ่ง ...

มันเพิ่ม "คนอื่น" ในคำจำกัดความ enum ของคอลัมน์ "rtipo" ของตาราง "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;

-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 แบบสุ่มที่ไม่เกี่ยวข้องอย่างสมบูรณ์และคุณไม่ได้พยายามอธิบายใด ๆ แหล่งข้อมูลที่ไร้ประโยชน์
Jonathan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.