记录一个Mysql关于类型隐式转换引发的问题

先说结论教训
尽量避免在sql中使用不同类型的值进行操作,不然在程序运行中很有可能出现很多奇奇怪怪的问题就像以下sql,执行结果看上去会难以理解
在这里插入图片描述

以下是正文
(不想看我啰嗦可以跳到分析
某天,运营人员反馈说有一笔订单客户取消后没有生成售后单,通过管理台手工触发生成售后单一直报“售后单已存在”,让技术这边帮忙看看什么原因。
于是我登录了管理台查看了该订单,该订单客户已经付过款,付款后该订单拆单生成了两笔子订单,客户取消订单后其中一笔子订单已经生成了售后单,另外一笔子订单没有对应的售后单,手工触发生成售后单,返回信息说“售后单已存在”。
至此,有了明确的信息,打开开发工具,订位到代码返回信息的位置,分析了对应的逻辑,逻辑大概就是在生成售后单前,查询一遍数据库中是否存在该子订单的售后单,有对应售后单则不进行重复生成,使用的sql如下

select count(1) from 售后表 where order_id = #{orderId}

于是我连上生产的数据库(小公司没有DBA。。。)执行了以下sql
在这里插入图片描述
其中引号内的字符串为没有生成售后单对应子订单的主键。
到这我感觉有点迷,这不是没有查到吗,怎么会报“订单已存在”呢?
于是我只能去查看生产的日志了,最总找到的日志中,执行的sql长这样:

select count(1) from 售后表 where order_id = ?

入参是(Long)1149156865679032322
看上去也没啥问题毕竟值都对上了,到这里我没有意识到带引号和不带引号会使结果天差地别,毕竟订单表的主键确实使用的是Long类型,这里传入的参数也是Long类型,于是走了很多岔路去排查问题,浪费了很多时间,最后直到我执行了以下sql
在这里插入图片描述
What for ?!!!
我查询的明明是22结尾,怎么给我查询出来23结尾的数据,我用的是等号啊!
直到后来,我看到了售后表的表结构,order_id居然变成了varchar类型。。。。
至此,这个问题的来龙去脉我算是搞清楚了
分析
订单表的主键是Long类型,售后单表存储订单表主键的字段order_id是varchar类型,在生成售后单判断售后单是否已存在的逻辑中,执行的sql传入Long类型的order_id去查询varchar类型的售后单表中订单主键,sql的where条件等号左边是varchar,右边是数字,进行了隐式类型转换,导致查询结果有误,查询到另一子订单的售后单记录,程序判断订单对应售后单已存在,报“订单已存在”,且没有继续生成售后单。
重要的事说三遍:
MySql执行sql切记不要让sql进行类型转换!!!
MySql执行sql切记不要让sql进行类型转换!!!
MySql执行sql切记不要让sql进行类型转换!!!

以上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值