什么是隐式类型转换
MySQL 中对隐式转换的定义:
When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly.
翻译下
当操作符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。
举个例子,当操作数是字符跟数字时, MySQL 会根据使用的操作符,转换字符到数字或转换数字成字符。
案例一: 字符串转换为数字
mysql > SELECT 1+'1';
结果:
mysql > 2
案例二: 数字转换为字符串
mysql -> SELECT CONCAT(1024,' andyqian');
结果:
'1024,' andyqian';
此时CONCAT(字符拼接)函数就将1024进行了隐式类型转换。
看一下官方的隐试转换说明:
- 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换
- 两个参数都是字符串,会按照字符串来比较,不做类型转换
- 两个参数都是整数,按照整数来比较,不做类型转换
- 十六进制的值和非数字做比较时,会被当做二进制串
- 有一个参数是 TIMESTAMP 或 DATETIME,并且另外一个参数是常量,常量会被转换为 timestamp
- 有一个参数是 decimal 类型,如果另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较
- 所有其他情况下,两个参数都会被转换为浮点数再进行比较
如何避免
之所以有隐式转换,一大部分是因为表设计的不够规范,如果我们可以在设计表结构时规避这些问题,比如一些枚举值,就不要用0,1,2这种魔法字符串代替,而是用真实有意义的枚举来代替,就可以规避该问题,不至于写sql 时搞不清字段的类型。
如果我们在进行sql生成时严格定义字段的类型,比如用mybatis时,不要在SQL语句里面写死这种预定义值,而是由参数传入,大部分就可以避免该情况的发生。