前言:
了不起学弟:学长最近工作怎么样啊,有没有遇到什么问题,可以跟我们分享一下啊!
了不起:有,一个生产问题,我和你们来说道说道。
正文:
背景是这样的,项目里有一个报表,没有数据了。然后排查了一下,数据确实没有。
我们的数据流向是,业务库到数据处理库(通过存储过程),那问题就出现在了存储过程上。我去手动执行,执行的sql语句确实是报错了。
报错的问题:Truncated incorrect DOUBLE value:.......
这个报错的的意思是数据不匹配。
我的语句大概是 insert into select ......
我limit 1,然后用结果去生成insert 语句可以正常插入。那说明数据是没问题。比对了一下insert后, 和select出的字段类型是否匹配,也是没问题的。
那么问题可能就出现在select语句里。通过去缩小select字段的范围,缺人字段没什么问题,再通过一行行注释掉 innerjoin的语句,最终确定在有一条innerjoin语句的问题。
仔细端详了一下才发现,innerjoin on后面的两个字段的类型不一样。这才导致insert into select 报错。
那为什么select没问题,insert into select就会出现问题呢。
这就要涉及到mysql隐式转化了。
在普通的select语句中,我们select * from A inner join B on A.id=B.xid;
如果a.id是varchar,B.xid是int,那这样子的一条语句是可以去执行的,mysql会对其进行隐式转化,转化成功就不会报错。
如果是用在insert into select,再这个过程中,mysql需要讲select语句中的每一行映射到目标表相应列中,如果无法进行隐式转化,类型又不一样就会报错。
解决方案:使用cast函数、concat函数处理编程varchar类型,或者convert函数。所以当我们之后再写sql语句中,最好是养成一个良好的习惯,对于不同类型的条件,一定要去转化。虽然mysql是可以帮助我们去做这个自动转化的,但是不防出现一些特殊的情况,让你去忘记了有这么回事。就导致了这一次的生产问题。