如何在MySQL中的ENUM类型列中添加更多成员?

时间:2009-10-01 04:55:50

标签: mysql enums alter-table

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类型列。

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 |
+----------------+

7 个答案:

答案 0 :(得分:93)

您的代码适合我。这是我的测试用例:

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_TABLES还是STRICT_ALL_TABLES?这可能会导致错误,而不是MySQL在这种情况下会给你的通常警告。

另一个编辑:好的,我现在看到表中的值肯定不在新的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;

答案 1 :(得分:93)

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

答案 2 :(得分:72)

我和Asaph的discussion可能不清楚,因为我们来回走了很多。

我认为我可能会澄清我们在未来可能面临类似情况的其他人的话语结果:

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'值时,此问题才会显现。

BOTTOM LINE:

如果您不希望您的成员集在定义后更改,则仅使用ENUM。否则,查找表更容易更新和修改。

答案 3 :(得分:2)

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

答案 4 :(得分:1)

这是另一种方式...

在表“ firmas”的列“ rtipo”的枚举定义中添加“其他”。

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;

答案 5 :(得分:0)

仅供参考:一个有用的模拟工具 - 带有Wampserver 3.0.6的phpMyAdmin - 预览SQL:我使用'预览SQL'来查看在保存列之前生成的SQL代码以及对ENUM的更改。 Preview SQL

上面你看到我已经输入'福特','丰田'进入ENUM但我得到语法ENUM(0),这会产生语法错误Query error 1064#

然后我复制并粘贴并更改SQL并通过SQL运行它,结果为正。

SQL changed

这是我经常使用的quickfix,也可以用于需要更改的现有ENUM值。认为这可能有用。

答案 6 :(得分:-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)");
  }

Before adding new value

After adding new value