MySQL 隐式转换的坑

2023年 10月 26日 61.4k 0

1、发现问题

开发拿到一个SQL问我,为什么一个SQL得不到想要的结果
原本身SQL较复杂,掩盖了简单的问题。这里我用测试数据做一个场景复现,并深入了解问题背后的MySQL原理

2、问题复现

创建测试表,并插入测试数据

create table test_convert
(id int,
str1 varchar(50),
str2 varchar(50),
num DECIMAL(65,0)
)
;

insert into test_convert
select 3,'10004100011000510086','123',10004100011000510086
union all
select 4,'10004100011000510087','aaa',10004100011000510087;
select * from test_convert;

表数据如上。

select * from test_convert where str1 = 10004100011000510086;

执行结果如上 10004100011000510087 的数据也跟着查出来了

3、分析原因

我第一个反映就是看看MySQL是不是改写了我的语句

explain
select * from test_convert where str1 = 10004100011000510086; -- 结果错误不会产生warnings
show warnings;

通过show warnings 查看 发现即没有警告出现,优化器也没有改变我的语句

细心的朋友可能已发现,str1字段是varchar(50)字符型, 我的sql语句比较是数值型,这里发生了隐式转换

通过查看官方文档,可以得到 字符型与数值型比较,最终是双双都转化为浮点型来比较

我以前记得转换的时候如果有异常至少会报warnings

但上述语句却没有告警

那我就再做几种场景的试验

a) 表字段为数值型,比较值为字符串,且不可转换

select * from test_convert where id = '3a'; -- 结果错误但有warnings
show warnings;


这种情况,结果是错误的。但MySQL给了告警

b) 表字段为字符型,比较值为数值型,可以转换,但会丢失精度

select * from test_convert where str1 = 10004100011000510086; -- 结果错误不会产生warnings
show warnings;



这种情况,结果是错误的。但MySQL不会告警

c) 表字段为字符型,比较值为数值型,可以转换,且不可转换

select * from test_convert where str2 = 0; -- 结果错误但有warnings
show warnings;



这种情况,结果是错误的。但MySQL给了告警

4、给一个总结

出现这种因隐式转换产生的错误,实在是低级错误

第一个是强制开发绝对不允许隐式转换发生
第二个是给当下一些流行的审核工具提个需求。 这种产生隐式转换的语句应该拦住,不允许执行。

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论