ChatGPT解决这个技术问题 Extra ChatGPT

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

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)

从汽车制造商输出中选择不同的国家:

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

大多数 ALTER TABLE 命令将完全重写整个表。 mysql 是否足够聪明,不能用 enum 做到这一点?
enum 只是一个花哨的整数,具有字符串表示形式。在末尾添加项目很好,因为您只需添加有意义的旧值。但是更改顺序/删除枚举将使这些数字未定义。 (例如,1=>意大利,2=>德国),然后扩展将是(1=>意大利,2=>德国,3=>瑞典)。
@John 取决于。对于 MariaDB,从 10.3.7 开始,可以在枚举末尾添加新值 inplacemariadb.com/kb/en/library/…
@John 我刚刚用 Mysql 测试了这个,现有的数据行不受影响。
@AbdullahKhan 现在我也获得了一些经验:Mysql 有时无需修改就可以做到,有时它会重新创建整个表。这取决于内部状态,例如它有多少枚举以及您要添加多少,我不记得具体细节,但如果您只有几百个枚举,它无需重新创建就可以工作 IF:您不修改任何枚举,你只在最后添加新的。
A
Asaph

你的代码对我有用。这是我的测试用例:

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;

我的 carmake 表中有不止一列。这和它有什么关系吗?
@Zaid 这么说要小心。 MySQL 因允许垃圾进入 ENUM 列而臭名昭著。例如,它将默默地将不合格的值转换为空字符串。您是否 100% 确定您没有任何冒犯性的价值观?没有空字符串?没有前导或尾随空格?案例差异?重音字符?
@Zaid 我认为您的表中确实存在更新后的 ENUM 定义中缺少的值。您的新定义只允许瑞典和马来西亚。您的表有美国、印度、德国......在您的新 ENUM 中不允许使用这些值。如果您要在保留 ENUM 的原始成员的同时添加瑞典和马来西亚,则需要在 ALTER 语句中重新列出所有原始 ENUM 值以及 2 个新值。
@Zaid 不客气。如果您使用带外键的国家/地区表而不是我之前建议的 ENUM,您将能够简单地为新国家/地区添加行。顺便说一句:如果您发现我的建议有帮助,请将我的答案标记为正确 :)
-1 因为不清楚这里的实际解决方案是什么。有太多的谈话和很多“试试这个,哦,试试这个吧。”最初的响应甚至没有回答 OP 的实际问题 - 直到后来你才意识到问题是什么,然后你进入简单的代码示例,这些示例对寻找这个问题/答案的人来说实际上没有任何意义晚些时候。您编辑的上下文是/曾经是暂时的,并且不再明显。
Z
Zaid

重要提示:这是一个遗留答案

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

我想我可能会澄清我们演讲的结果,以便将来可能面临类似情况的其他人受益:

ENUM 类型的列是非常难以操作的野兽。我想在我的 ENUM 中的现有国家集中添加两个国家(马来西亚和瑞典)。

似乎 MySQL 5.1(这是我正在运行的)只能通过重新定义现有集合来更新 ENUM,除了我想要的:

这不起作用:

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

原因是 MySQL 语句将现有 ENUM 替换为仅包含条目 'Malaysia''Sweden' 的另一个 ENUM。 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。否则,查找表更容易更新和修改。


我会冒险一个更强的底线......“只有当你 100% 死肯定肯定值永远不会改变时才使用 ENUMs”。如果表变大,如果您不得不更改这些值,那将是一件痛苦的事情。
我不确定我是否同意这个底线。相信我,我根本不喜欢 ENUM,但我没有看到添加到可能的 ENUM 的危险。 ENUM 的核心是 0 -> 选项 1、1-> 选项 2 等的映射。添加它不应该引起问题。
@JoshStrange 这并不是什么危险,当您的 ENUM 的顺序很重要时(例如,用于订购时),这可能会带来巨大的不便。
我认为重要的是在底线中说这仅对旧版本的 MySQL 有效,因为据我所知,使用较新的版本没有问题。
H
Hannele

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

不知道为什么这没有得到更多的支持。这很简单,对我有用。
我可以确认它也适用于 MySQL 5.7。
看起来它也适用于 MySQL 8
A
Antonio

这是另一种方式...

它将“others”添加到表“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;

A
Addi

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

上面你看到我在 ENUM 中输入了 'Ford','Toyota' 但我得到的语法 ENUM(0) 正在生成语法错误 Query error 1064#

然后我复制并粘贴并更改 SQL 并通过 SQL 运行它,结果是肯定的。

SQL changed

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


S
ShaileshKumarMPatel

mysql data truncated for column 'status' at row 1 enum 如果记录中存在旧值并且更改的 ENUM 不包含它,则可能在添加新枚举值时导致上述错误


A
Alj

如果你相信,这是可能的。呵呵。试试这个代码。

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


我看不出这会给桌面带来什么新东西。这个问题也纯粹是从 MySQL 的角度来看的。您的答案包含完全不相关的随机 PHP,并且您没有尝试解释其中的任何内容。无用的信息资源