一、现象
简单查询 in 语句中值多个时候,查询出来的数据不对;单独值查询时,没有数据,是对的结果。
二、原因分析
1) 查看表字段结构为 decimal 字段
2)猜测发生隐式转换发生精度丢失
去掉数值引号,查不出来结果,为正确结果
浮点数和大整数比较时候是近似比较,因为在比较前整数会转换成双精度浮点数;而双精度浮点数不能精确表示 64 位整数。整数通过 CPU 转换成浮点数,字符串是逐个数字在浮点数相乘运算中转换,其结果受计算机架构,编译器版本,优化级别等影响。
隐式转换的规则:
1、 两个参数中至少有一个是 null 时,比较的结果也是 null 只有使用 <=> 对两个 null 做比较时会返回 1,这两种情况都不需要做类型转换;
2、 两个参数都是字符串,按照字符串来比较,不做类型转换;
3、 两个参数都是整数,按照整数来比较,不做类型转换;
4、 十六进制的值和非数字做比较时,会被当做二进制串进行比较;
5、 一个参数是 timestamp 或者 datetime 类型,另外一个参数是常量,在比较之前,常量会被转换为 timestamp(in ( ) 运算除外);如果子查询返回单行整数值和 datetime 类型值进行比较,datetime 类型值回转换成整数进行比较;
6、 一个参数是 decimal 类型,另外一个参数是 decimal 或者整数,会将整数转换为 decimal 后进行比较,如果另外一个参数是浮点数,则会把 decimal 转换为浮点数进行比较;
7、 其余情况下,两个参数都会被转换为浮点数再进行比较。
3)为什么in条件一个的时候不会被查出来,一旦条件多了就会多数据出来
通过打开OPTIMIZER_TRACE 开关,跟踪 2 个 SQL 执行情况:发现优化器对 in 语句单个值进行了处理
1)QUERY: SELECT acc_prod_inst_id FROM func_prod_inst WHERE acc_prod_inst_id IN ('325240811021860243')
2)QUERY: SELECT acc_prod_inst_id FROM func_prod_inst WHERE acc_prod_inst_id IN ('365240821003929695','325240811021860243')
三、解决方案
acc_prod_inst_id 字段改为 bigint 或者 业务 SQL in 中数值不带引号
防止隐式类型转换
1)写sql的时候注意类型保持一致;
2)比较时候使用cast函数进行转换;