如何将数字枚举列转换为 tinyint?

Posted

技术标签:

【中文标题】如何将数字枚举列转换为 tinyint?【英文标题】:How do I convert a number enum column to tinyint? 【发布时间】:2019-06-05 22:54:57 【问题描述】:

在 Laravel 5.7 中开发,使用 mysql 数据库。在我的几个数据库列中,我有枚举类型 - 没有做我的研究并使枚举充满数字(0-2 或 0-3)。在阅读了利弊之后,我想摆脱枚举并将它们转换为 tinyint。

将表中列的类型更改为 tinyint 并将字符串 '0'、'1'、'2'、'3' 转换为 tinyint 的最佳方法是什么?

我真的不想在这个过程中丢失我的数据。

https://laravel.com/docs/5.7/migrations#modifying-columns 有关于修改列的信息,但是它不支持枚举:

只有以下列类型可以“更改”:bigInteger、binary、boolean、date、dateTime、dateTimeTz、decimal、integer、json、longText、mediumText、smallInteger、string、text、time、unsignedBigInteger、unsignedInteger 和 unsignedSmallInteger。

【问题讨论】:

【参考方案1】:

为了安全起见,我会使用临时列;

ALTER TABLE tbl ADD COLUMN _temp_col CHAR(1) COLLATE 'latin1_general_ci'; -- CHAR(1) is OK if you only have numeric ENUMs
UPDATE tbl SET _temp_col = col; -- ENUM values would be copied as is
ALTER TABLE tbl MODIFY COLUMN col TINYINT(1) UNSIGNED;
UPDATE tbl SET col = _temp_col; -- Values would be auto-converted to ints
ALTER TABLE tbl DROP COLUMN _temp_col;

【讨论】:

【参考方案2】:

用 MySQL-8.0 进行实验产生了以下转换。

ALTER TABLE 似乎转换为'x' -> x+1。所以我想根据下面的UPDATE 进行更改

select version();
|版本() | | :-------- | | 8.0.13 |
create table x (y enum ('0','1','2','3') );
insert into x values ('1'),('0'),('2'),('3')
select * from x
|是 | | :- | | 1 | | 0 | | 2 | | 3 |
alter table x modify y tinyint unsigned;
select * from x;
|是 | | -: | | 2 | | 1 | | 3 | | 4 |
update x set y=y-1
select * from x
|是 | | -: | | 1 | | 0 | | 2 | | 3 |

db小提琴here

【讨论】:

请注意,这实际上并没有转换枚举的值,只是将列表中的序数值转换为 int。所以enum ('10','11','12','13') 会转换成(1,2,3,4),比如this 是的,alter 将枚举值转换为其索引。因此,您的递减技巧仅适用于您在 ENUM 中的订单值。如果原始 ENUM 是 ('3', '2', '1', '0') 那就不同了。 您的回答可能会造成混淆。它不像set y = y - 1 那样简单,因为如果您有enum('3', '2', '1', '0'),您会注意到转换不会简单地将每个值加1

以上是关于如何将数字枚举列转换为 tinyint?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Postgresql 布尔值转换为 MySQL Tinyint?

如何在快递中将 TINYINT(1) 转换为 BOOLEAN?

java如何将接收到的数字自动转换为枚举

JOOQ:根据长度将 tinyint 映射到布尔值

将 TINYINT 添加到 Doctrine SQL 类型

如何将 PostgreSQL 数据库中的所有 SMALLINT 列转换为 BOOLEAN?