mysql中的隐式类型转化及实际mysql说明

Posted 安然_随心

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql中的隐式类型转化及实际mysql说明相关的知识,希望对你有一定的参考价值。

文章目录

当在不同类型的值之间比较时,mysql 就会进行类型隐式转化。另外,你也可以主动使用类型转化函数,来进行显示类型转化。主要参考文献:https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html

类型转化初步认识

首先我们先来看看比较常见两种的类型转化:

  1. 表中列的类型为 int , 条件是string;
  2. 表中列的类型为 string , 条件是int;

表中列的类型为 int , 条件是string

如果数据库表中目标列的类型为int, 条件是string, 则mysql 会将 条件值转化成 数字,然后在进行比较。

举例说明

测试表结构:

CREATE TABLE `test_ld` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
  `creator_id` int(11) DEFAULT NULL,
  `request_id` varchar(11) DEFAULT NULL,
  `topic` varchar(30) DEFAULT NULL,
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录创建时间',
  `modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '记录修改时间',
  PRIMARY KEY (`id`),
  KEY `idx_creator_id` (`creator_id`),
  KEY `idx_request_id` (`request_id`),
  KEY `idx_topic` (`topic`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8mb4 COMMENT='测试表';

表中数据结构:

执行查询:

select id, creator_id from test_ld where creator_id='1a2';

结果:

mysql 会直接将 ‘1a2’ 转化成 数字1(将非数字后的部分直接丢弃),然后进行比较。我们可以看看这个sql 的执行计划,还是使用到了idx_creator_id 这个索引的。


当使用 select * 时,还是走的索引(这里注意,后面还是会进行比较)

表中列的类型为 string , 条件是int

测试表结构同上,topic 列为字符串类型。

表中数据如下所示:

当对字符串类型的列进行比较时,会进行前缀比较(看上去效果是进行前缀比较,实际是 mysql 会转化成 浮点数的比较。1_test 转化成浮点数,就是 等于1,去掉后面的非数字字符);

看看执行计划:

当使用 select 选择只需要索引相关列时,还是可以走索引进行比较,但是ref 是空,因为最后匹配的值可能是 9223372036854775806a ,或者9223372036854775806XXXX 等,这个是不确定的

但是当使用select * 的样式是,mysql 就不使用索引了。本来mysql 就不确定 具体的值是,不知道有多少索引满足条件,而且select * 还需要回表,所以mysql 觉得还不如全表块。

上述的select * 和这种等价,都是需要回表的

对比一下,可以完全直接匹配索引的,输入参数是string, 列也是string 的,还是优先走索引(普通的、符合常识的case)

explain select * from test_ld where topic='9223372036854775806';

隐式类型转化过程的坑

对字符串类型 执行查询,使用 int 类型参数方面的

关于int 0

执行如下sql :

select id,`topic` from test_ld where topic=0;

关于超长串

对于列是字符串类型,传入 int 类型的参数,mysql 会将 db 中的数据列的值 和输入的值 都转化成浮点数进行比较。但是 超大的数字 转化成浮点数时是不准确的。

select * from test_ld where topic=9223372036854775806;

mysql 隐式类型转化规则

  1. 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换

  2. 两个参数都是字符串,会按照字符串来比较,不做类型转换

  3. 两个参数都是整数,按照整数来比较,不做类型转换

  4. 十六进制的值和非数字做比较时,会被当做二进制串

  5. 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp

  6. 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较

  7. 所有其他情况下,两个参数都会被转换为浮点数再进行比较

以上是关于mysql中的隐式类型转化及实际mysql说明的主要内容,如果未能解决你的问题,请参考以下文章

Mysql中的隐式转换

javascript中的隐式类型转化

如何检测 MySQL 中的隐式提交?

MySQL令人咋舌的隐式转换

Scala中的隐式转换|理解

MySQL性能优化:MySQL中的隐式转换造成的索引失效