「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战」
第一点,如果将数字存储到这个枚举的列中,则会将该数字视为可能值得索引,并且存储的值是具有该索引的枚举成员。需要注意到,如果引用了数值,即使枚举值列表中没有匹配的字符串,但他仍会被解释为索引。如果你没有使用过枚举或者是对枚举类型不够理解,你看到这句话的时候可能会很懵,不知道讲的是啥意思。
接下来我们就以案例的形式给大家去验证一下,这句话的意思以及这句话可能会产生的一些误区。
现在我们插入一条 SQL语句,这里所插入的 SQL 语句是比较奇怪的。 gender 字段我们插入的是 male 是没有问题的,但是 grade 字段允许值列表是 0、1 和 2,但是都是字符串,但是我这里插入的是一个整型数字 2,我们实现插入,看看会得到一个什么样的效果,。插入 SQL 语句如下。
INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (3, 'abc', 'male', 2);
SQL 语句执行的结果如下所示。
那么可以看到,这条数据是能够插入成功的。我们去看一看great 瑞的这个字段里面存储的一个什么样的值。查看 SQL 语句如下所示。
select id, name, gender, grade from t_suitable_data_type;
查询结果如下所示。
可以看到,我们插入这条数据是 id 为 3 这样一条记录,grade 为 1。那么这是为什么呢?这就是因为你所插入的,其实 MySQL 已经把它翻译为的这个索引,因为你插入的是一个字面量的值,是一个整型数值,但是枚举定义的是一个字符串,那么对于你插入这个整型的,MySQL 数据库会把它翻译为索引。由于我们的 grade 它允许的字面量是0、1 和 2,而且这个 1的正好是 ,所以这里的 grade 字段值就是 1。
我们再去看一个插入语句。这条插入语就比较好理解了,我们直接去插入了 grade 字段的字面值是 2,也就是允许值列表是字符串 2。插入 SQL 语句如下所示。
INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (4, 'abc', 'male', '2');
执行结果如下所示。
插入成功之后,查询一下当前的数据表的数据。
可以看到也是符合预期的,我们插入的就是这个枚举值的允许值列表的 2。 我们再去做一个插入,我们插入的呢是字符串 3。但是我们需要注意的是 `grade 的里面允许值列表是没有字符串 3。那么这条语句是否会执行成功呢,我们尝试执行一下。
INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (5, 'abc', 'male', '3');
执行结果如下所示。
可以看到这条 SQL 也没有报错,执行成功了。这是因为 MySQL 数据库在检查插入这个枚举值的时候,首先它会去判断枚举值是否在允许值列表里面, 3 是不在允许值列表里面的,然后 MySQL 数据库就会做第二步操作,它会尝试将这个值呢转换为枚举值允许值列表的索引,也就是转变为整形 3。那么转变为整形 3 以后,再去匹配对应的索引,也就是 grade 字符串 2 的索引,我们去再看一下这个表结构。
desc t_suitable_data_type;
执行结果如下所示。
那么由于这个 grade的允许值列表是 0、1 和 2,对应到 2 这个字符串的索引正好是 3。所以 MySQL 数据库插入数据就是 2。通过 SQL 语句验证一下。
select id, name, gender, grade from t_suitable_data_type;
执行结果如下所示。
从上图可以看到结果也是符合预期的。我们插入的 id 是 5,那么对应到的 grade 是 2,也就是 MySQL 做了两步的判断操作,它会去给你尝试以索引的形式去匹配到允许值列表。这就是 MySQL 数据库对这个字面量值的一个解释。
最后一条插入语句,这个前面三个字段都是一样的。最后一个 grade 不太一样。grade我们插入的是四。由于4 没有出现在这个允许值列表里面,而且允许值列表的最大索引是 3。所以对应到这条插入语句呢, MySQL 数据库无法执行的。
INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (6, 'abc', 'male', '4');
执行的结果如下所示。
可以看到,这里报错了,也就是告诉你 grade 这一列不出现在允许值列表里面, MySQL 数据库不允许插入。
就是关于这个枚举值字面量的一个理解,大家应该理解了。不理解的多读读,然后去做一些尝试,你就会理解是什么样的含义。
第二点,当在枚举列上去使用 SUM() 或者是 AVG() 等聚合函数时,因为这些函数的参数必须是一个数字,所以 MySQL 会自动使用它们的索引值作为参数,这一点比较容易理解。我们就去直接执行一下,他看一看结果。
select sum(gender) from t_suitable_data_type;
执行的结果如下所示。
可以看到,对 gender 这一列去 SUM 的时候,它的值是 4,这其实就是实现对 gender 的一个索引的一个相加。我们把。由于当前表的 gender 列的值都 male,而 male 的索引都是 1,所以最后的结果是 4。
接下来看看 AVG() 聚合函数,AVG() 用于计算平均值。
select avg(gender) from t_suitable_data_type;
执行的结果如下所示。
从图可以看到,由于每一个 gender 字段的值都是 male,所以它的索引也仍然就是 gender 的对应的索引。这就是聚合函数的索引值计算的时候的一个规则,它会根据这个枚举的索引进行一个计算。
第三点,因为枚举的类型存储的是枚举时的内部索引,所以枚举值会根据其索引进行一个排序。我们这里所要想表达的一个点就是告诉你,如果你对枚举值进行一个排序,MySQL 数据库会根据枚举值对应的索引的 id 进行一个排序。我们去验证一下这一点。
这里还是去实现一个插入 SQL 语句。我们这里的插入id 是 7,对于 gender 字段的值我们插入是 female,因为之前插入了都是 female,我们想要去演示一个排序的效果,所以这里插入了一个 female ,grade我们插入的是字符串 0,也就是允许值列表的第一个。
INSERT INTO `db_mysql_escape`.`t_suitable_data_type`(`id`, `name`, `gender`, `grade`) VALUES (7, 'abc', 'female', '0');
执行的结果如下所示。
插入成功之后,我们去实现对
gender 的字段的一个排序。我们实现按照 gender 对当前的这个数据表中的数据进行一个排序。我们看一看结果。
select * from t_suitable_data_type order by gender;
排序结果如下所示。
可以看到 male 排在最前面,female排在最后,这就是按照索引的值排序,因为 male的索引是 1,female 索引是 2,它就会按照这样的一个值去排序,并没有按照字符的顺序去排序。但是如果我们确实想要按照字符的顺序去排序,而不是按照索引的顺序去排序,我们就可以去给他加上一些转换为字符。通过 CAST 函数实现强制类型转换,是 MySQL 提供的,我们将 gender转换为 字符串类型,此时就会按照这个字符序进行排序。
select * from t_suitable_data_type order by cast(gender as char);
执行结果如下所示。
可以看到 female 排在最前面。
CONCAT() 实现对类型转换,返回串联参数的结果的字符串。可能有一个或多个参数。如果所有的参数都是非二进制字符串,结果是一个非二进制字符串。如果参数包括任何二进制串,结果是一个二进制串。一个数字参数被转换为等值的二进制字符串格式,如果要避免这种情况,可以使用显式类型转换。
CONCAT() 和 CAST 都将枚举转变为自符串,然后再去排序就能够得到根据你所看到的字符串的顺序进行排序。
好,这就是关于枚举类型的三个特性的点,也是需要注意的事项。那么如果你不能够好好的理解关于枚举的特性,是很容易在枚举的使用上出错的。