臭名昭著的 MySQL ENUM 类型 ( 上 )

作者简介:大家好,我是码炫码哥,前中兴通讯、美团架构师,现任某互联网公司CTO,兼职码炫课堂主讲源码系列专题


代表作:《jdk源码&多线程&高并发》,《深入tomcat源码解析》,《深入netty源码解析》,《深入dubbo源码解析》,《深入springboot源码解析》,《深入spring源码解析》,《深入redis源码解析》等


联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

MySQL 中,对于那些取值只有两三个,或者五个以内的值,想必,大多数人使用的应该都是 ENUM 类型吧,而剩下的另一部分人,应该都是使用 TINYINT(1) 。 我,就是剩下的那部分人。

一方面我真的是太懒,虽然 MySQL 提供了丰富的数据类型,但我用到的真心不多,也就那么几个 INT(11)TINYINTVARCHAR 和 TEXT

我为什么不用 ENUM 类型?

因为我在入门的时候,就跳进了一个大窟窿,而且久久未上岸。

事情的经过是这样的:

  1. 假设我们要保存的一列只有两个值 true 和 false ,那么我们第一时间想到的,自然是使用 enum('T','F') 来表示对吧

    所以,我们创建了下面这个表

        CREATE TABLE `b` (
              `k` ENUM('T','F') NOT NULL
        );
简单起见,我们只有一个字段
  1. 创建成功后,我们就会往里面插入数据,当然了,我们并不按正常套路出牌,而是使用下面的 SQL 语句
        INSERT INTO `b` (`k`) VALUES ('W'), ('T'), ('F');
这条语句能执行成功吗?

显然,不能的

执行的结果为
        ERROR 1265 (01000): Data truncated for column 'k' at row 1
这在最新的 MySQL 版本是直接报错的,因为最新的几个 MySQL 版本都开启了严格模式。

如果关掉严格模式,或者使用比较古老的版本,仅仅是发出了一个警告而已
        Query OK, 3 rows affected, 1 warning (0.00 sec)
        Records: 3 Duplicates: 0 Warnings: 1
我们可以使用 `SHOW WARNINGS;` 语句查看刚刚的警告
        mysql> SHOW WARNINGS;
        +---------+------+------------------------------------------+
        | Level   | Code | Message                                  |
        +---------+------+------------------------------------------+
        | Warning | 1265 | Data truncated for column 'k' at row 1 |
        +---------+------+------------------------------------------+
        1 row in set (0.00 sec)
当然了,如果你以为数据是正确插入的,可就大错特错了,看看下面的语句
        mysql> SELECT COUNT(DISTINCT k) FROM b;
        +---------------------+
        | COUNT(DISTINCT k) |
        +---------------------+
        |                   3 |
        +---------------------+
        1 row in set (0.00 sec)
是不是大跌眼镜,原则上来说,应该仅仅只有两个不一样的值 `T` 和 `F` ,而 `W` 竟然也能插入成功

对于这个问题,MySQL 官方还是作出了一点的解释的

「如果在 ENUM 列中插入无效值(即,允许值列表中不存在的字符串),则会插入空字符串 ( '' ) 作为特殊错误值,这个空字符串可以通过此字符串具有数字值 0 来区分 正常 的空字符串 」

是不是很绕口,很简单的规则,就是说如果往 enum 列中插入了无效的值,可以被插入,但插入的是一个特殊的空字符串,而该空字符串的数值是 0

所以,使用 enum 就要很小心了。

就因为这个原因,我始终没有碰 enum ,当然了,另一个原因是如果要添加其它允许的值,则需要修改默认表结构,这,往往是得不偿失的。

本章节,我们就来讲讲这个臭名昭著的 enum 类型。

MySQL ENUM 数据类型

  1. 首先,要说的是「 ENUM 类型其实是一个字符串类型 」,虽然作用很像 C 或 C++ 中的枚举类型。
  2. 其次,要说明的是,ENUM 类型的值都是从 允许值列表中选择
  3. 再次, 允许值 列表在创建表结构时就定义好的,表创建完成后可以使用 alter 语句来修改允许值列表

ENUM 数据类型能够带来很多好处,比如

  1. 数据更紧凑。因为 ENUM 列一般都是有限的值,一般不多余 5 个这样,这就比保存 true 或 false 节省空间多了。因为 MySQL 会在创建或者修改表结构时将 enum 允许的值自动编码为数字,而这个数字一般的分配空间为 1~2 字节 ( byte ) ,具体取决于实现。

    例如,将值为 medium 的100万行插入表将需要 100 万字节的存储空间,而如果将实际字符串 medium存储在 VARCHAR 列中则需要 600 万字节。

  2. 更好的可读性,虽然在存储的是数字,但在输入和输出时使用的都是对应的允许值。

虽然 enum 有这两个极大的好处,但也有不少的坏处,前面提到的就是其中之一

至于具体有哪些坏处,我们下一章节再来阐述吧

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值