ChatGPT解决这个技术问题 Extra ChatGPT

How do I add more members to my ENUM-type column in MySQL?

The MySQL reference manual does not provide a clearcut example on how to do this.

I have an ENUM-type column of country names that I need to add more countries to. What is the correct MySQL syntax to achieve this?

Here's my attempt:

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

The error I get is: ERROR 1265 (01000): Data truncated for column 'country' at row 1.

The country column is the ENUM-type column in the above-statement.

SHOW CREATE TABLE OUTPUT:

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)

SELECT DISTINCT country FROM carmake OUTPUT:

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

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

Most ALTER TABLE commands will completely rewrite the whole table. Is mysql clever enough to not do that with enum ?
enum is just a fancy integer, with a string representation. adding items to the end is fine, since you just add meaning old values. but changing the order / removing enums will make those numbers undefined. (eg. 1=>italy, 2=>germany), then extending will be (1=>italy, 2=>germany, 3=>sweenden).
@John depends. For MariaDB, adding new values at the end of the enum can be done inplace since 10.3.7: mariadb.com/kb/en/library/…
@John i just tested this with Mysql and the exisitng data rows are not affected.
@AbdullahKhan by now I also gained some experience: Mysql sometimes can do it without modification, sometimes it will recreate the entire table. It depends on internal states, like how many enum it has and how many you are adding, I don't recall the specifics but if you have just a couple hundred enums it will work without re-creation IF: You do not modify any enum, you only add new ones at the end.
A
Asaph

Your code works for me. Here is my test case:

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)

What error are you seeing?

FWIW this would also work:

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

I would actually recommend a country table rather than enum column. You may have hundreds of countries which would make for a rather large and awkward enum.

EDIT: Now that I can see your error message:

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

I suspect you have some values in your country column that do not appear in your ENUM. What is the output of the following command?

SELECT DISTINCT country FROM carmake;

ANOTHER EDIT: What is the output of the following command?

SHOW VARIABLES LIKE 'sql_mode';

Is it STRICT_TRANS_TABLES or STRICT_ALL_TABLES? That could lead to an error, rather than the usual warning MySQL would give you in this situation.

YET ANOTHER EDIT: Ok, I now see that you definitely have values in the table that are not in the new ENUM. The new ENUM definition only allows 'Sweden' and 'Malaysia'. The table has 'USA', 'India' and several others.

LAST EDIT (MAYBE): I think you're trying to do this:

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

There's more than one column in my carmake table. Could that have anything to do with it?
@Zaid be careful about saying that. MySQL is notorious for allowing garbage into ENUM columns. It will silently convert non-conforming values to empty strings, for instance. Are you 100% sure you don't have any offending values? No empty strings? No leading or trailing whitespace? Case differences? Accented characters?
@Zaid I think you do have values in your table that are absent from your updated ENUM definition. Your new definition only allows Sweden and Malaysia. Your table has USA, India, Germany... None of those values will be allowed in your new ENUM. If what you are trying to do is add Sweden and Malaysia while preserving the original members of the ENUM, you'll need to relist all the original ENUM values plus the 2 new ones in your ALTER statement.
@Zaid You're welcome. If you use a countries table with a foreign key instead of the ENUM as I suggested early on, you'll be able to simply add rows for the new countries. BTW: If you've found my suggestions helpful, please mark my answer correct :)
-1 For lack of clarity on what the actual solution is here. There's too much conversation and a lot of "try this, oh well try this instead." The initial response doesn't even answer the OP's actual question - it's not until later that the you realize what the problem was, and then you go into simple code samples that don't actually mean anything to someone who is finding this question/answer at a later time. The context of your edits is/was temporal, and is no longer obvious.
Z
Zaid

Important note: this is a legacy answer

The discussion I had with Asaph may be unclear to follow as we went back and forth quite a bit.

I thought that I might clarify the upshot of our discourse for others who might face similar situations in the future to benefit from:

ENUM-type columns are very difficult beasts to manipulate. I wanted to add two countries (Malaysia & Sweden) to the existing set of countries in my ENUM.

It seems that MySQL 5.1 (which is what I am running) can only update the ENUM by redefining the existing set in addition to what I want:

This did not work:

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

The reason was that the MySQL statement was replacing the existing ENUM with another containing the entries 'Malaysia' and 'Sweden' only. MySQL threw up an error because the carmake table already had values like 'England' and 'USA' which were not part of the new ENUM's definition.

Surprisingly, the following did not work either:

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

It turns out that even the order of elements of the existing ENUM needs to be preserved while adding new members to it. So if my existing ENUM looks something like ENUM('England','USA'), then my new ENUM has to be defined as ENUM('England','USA','Sweden','Malaysia') and not ENUM('USA','England','Sweden','Malaysia'). This problem only becomes manifest when there are records in the existing table that use 'USA' or 'England' values.

BOTTOM LINE:

Only use ENUMs when you do not expect your set of members to change once defined. Otherwise, lookup tables are much easier to update and modify.


I would venture a stronger bottom line... "only use ENUMs when you are 100% dead certain positive that the values will never change". If a table grows large, it will be a pain if you ever have to change those values.
I'm not sure I agree with that bottom line. Trust me I don't like ENUM's at all but I don't see the danger in ADDING to the possible ENUM. ENUM is, at it's core, a mapping of 0 -> Option 1, 1-> Option 2, etc. Adding to that shouldn't cause an issue.
@JoshStrange It's not so much a danger, it can be a huge inconvenience when the order of your ENUM is important (for example, when used for ordering).
I think it's important also to say in the bottom line that that is valid only with legacy versions of MySQL because for what I understand, with newer ones there is no problem.
H
Hannele

In MYSQL server version: 5.0.27 i tried this and it worked fine for me check in your version

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

Not sure why this isn’t upvoted more. It’s simple, and it works for me.
I can confirm it works on MySQL 5.7 as well.
Looks like it works for MySQL 8 too
A
Antonio

Here is another way...

It adds "others" to the enum definition of the column "rtipo" of the table "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;

A
Addi

FYI: A useful simulation tool - phpMyAdmin with Wampserver 3.0.6 - Preview SQL: I use 'Preview SQL' to see the SQL code that would be generated before you save the column with the change to ENUM. Preview SQL

Above you see that I have entered 'Ford','Toyota' into the ENUM but I am getting syntax ENUM(0) which is generating syntax error Query error 1064#

I then copy and paste and alter the SQL and run it through SQL with a positive result.

SQL changed

This is a quickfix that I use often and can also be used on existing ENUM values that need to be altered. Thought this might be useful.


S
ShaileshKumarMPatel

mysql data truncated for column 'status' at row 1 enum Above error may be caused during adding new enum values, if old values exist in records and altered ENUM do not include it


A
Alj

It's possible if you believe. Hehe. try this code.

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

Before adding new value

After adding new value


I don't see how this brings anything new to the table. The question is purely from a MySQL standpoint as well. Your answer incorporates random PHP that is completely irrelevant and you make no attempt at explaining any of it. Useless resource of information