MySQL 数据库之不要轻易使用枚举

2,652 阅读4分钟

「这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战

我的建议是不要去使用枚举。接下来我们就来深入的探讨下为什么会有这样的一个结论。

我们去说一说枚举的特性,枚举的类型值都是从允许值列表中去选择的。而且列表是在创建表结构的时候,就定义好的,那么表创建完成之后,我们还可以去使用 LT 语句去修改允许值列表。在存储上,这个枚举会将允许值列表变成数字索引。索引值会从 1开始。

image-20210322031343562

上图是我我绘制的一张表,它代表的是我们有一个这个枚举字段类型。那么允许值列表是 malefamele ,它的索引就是 1 和 2。其中 NULL 和 0 是一个特殊的索引,用于标识 NULL 值和空字符串。那么这样的设计会有两点好处。第一点,存储数字数据会更加紧凑,而且节省了存储空间。第二点,允许值提前就要定义好,在存储的时候,MySQL 就可以去帮助我们检查数据的正确性。

即使是枚举类型有这样的好处,它也是存在很多弊端的。为了验证这些弊端,我们先来去创建一张数据表,用于句演示讲解。

创建数据库表 SQL 如下。

CREATE TABLE `db_mysql_escape`.`t_suitable_data_type` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(32) NOT NULL,
    `gender` ENUM('male', 'female') NOT NULL,
    `grade` ENUM('0', '1', '2') NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

数据表创建好了之后,我们就可以看一看数据库表的一个数据类型以及它的结构。

desc t_suitable_data_type;

查看数据表类型以及结果如下所示。

image-20210322050330439

从上图可以看到,gender 是一个枚举类型,接受的允许值列表分别是 malefemale,而 grade 接触的允许值列表是 0、1 和 2。除此之外就是 idname 这样的两个简单属性。

我们呢先去做一个最基本的验证,插入数据需要与枚举的允许值列表相匹配,也就是刚刚所讲的枚举类型,它会让 MySQL 数据库帮助我们检查数据的正确性,我们去验证一下。

插入一条正确的数据。

INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (1, 'abc', 'male', '1');
​

我们去执行一下这条插入语句。那么可以看到,这条插入语句分别往 idnamegender,,grade 插入 1,itzmkmale,'1',由于 male与 '1' 都是定义在这个允许值列表里面的。所以说呢这条语句是可以插入成功的,也就是这条语句是合法的,此时插入成功。下图所示。

image-20210322051956276

此外,我们再去看一个不合法的语句,我们有该如何实现呢。

插入一条错误的数据。

INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (2, 'abc', 'male', '9');

可以看到,通过上面的 SQL 知道,gender在里面插入了 male,它是合法的。但是 grade,我们设定的允许值列表是0、1 和 2。但是我们插入的字符串是 9,那么此时就会是不合法的。下图所示。

image-20210322052119215

可以看到这个数据库给我们了一个 error,插入的数据被截断 ,也就是我们所插入的数据不合法的,此时就会插入失败。

image-20210322053548253

我们可以看到只有一条这个数据,也就是我们刚刚所插入的。

这里有一个问题,能不能获取到枚举记录的索引呢?

前面讲过枚举记录,MySQL 数据库会保存的是索引。我们能不能通过 SQL 语句去查询到枚举值的索引记录呢?当然是可以的。

查看枚举值对应的索引,我们只要给字段查询的时候,去加上一个零,MySQL 数据库知道我们想要去查询的是这个枚举的索引。比如 namegender + 0, gradernamegrade。查询 SQL 语句如下。

select name, gender + 0, grade from t_suitable_data_type;

查询结果如下图所示。

image-20210322053943975

从上图中,可以看到这里的 male 字段的一个索引是1,正如我们之前所说,枚举的索引是从1 开始,那么 male 就是 1,female 就是 2。这样我们就简单的讲解了枚举的一些特性,以及怎么样去查看枚举记录的索引。