在开发规范中,我们往往会要求研发避免在where条件中出现隐式类型转换,这么要求大概有以下两方面的原因:

  1. 隐式类型转换可能导致索引失效;
  2. 隐式类型转换可能产生非预期的结果。

注:这里说的是隐式类型转换。

我们可以看下官方关于类型转换的解释:

这里讨论以下情况:

In all other cases, the arguments are compared as floating-point (real) numbers.

回顾:一次研发提供过来的数据修正的sql:

 update tbjxxxxaccout set balancexxx=balancexxx+0.1 where bankxxx=6222000233022332111;

即,根据银行电子账户更新账户余额信息。执行后发现更新了多条数据(电子账户是唯一的),然后回滚操作;重新检查sql,发现bankxxx的条件忘记加引号,正确的sql应该是:

 update tbjxxxxaccout set balancexxx=balancexxx+0.1 where bankxxx='';

bankxxx的字段类型为varchar(20),在没有加引号的情况下发生了隐式数据类型转换,按官方的解释:这种情况的比较会转换为浮点型数据再去比较,即6222000233022332111会转化为string类型再转化为float类型来比较(注:至于为什么会先转换成string再转换成float,这其中内部机制我也没搞明白,有待考证)。

下面造几个数据做测试:

 CREATE TABLE `t_zw1` (

   `id` int(11) DEFAULT NULL,

   `account_id` char(19) DEFAULT NULL,

   `balance_amount` decimal(18,2) DEFAULT NULL

 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 insert into t_zw1 values(1, '', 18.9);

 insert into t_zw1 values(2, '', 108.1);

 insert into t_zw1 values(3, '', 180.3);

 insert into t_zw1 values(4, '', 2.3);

 insert into t_zw1 values(5, '', 33.3);

 root@zow 10:09:34>select * from t_zw1;

 +------+---------------------+----------------+

 | id   | account_id  | balance_amount |

 +------+------------------------------+----------------+

 |    1 | 6222000233022332111 |          18.90 |

 |    2 | 6222000233022332211 |         108.10 |

 |    3 | 6222000233022332311 |         180.30 |

 |    4 | 6222000233022334211 |           2.30 |

 |    5 | 6222000233022334311 |          33.30 |

 +------+---------------------+------------------------+

我们看下account为6222000233022332111 的情况:

 root@zow 10:17:02>select * from t_zw1 where account_id='';

 +------+---------------------+----------------+

 | id   | account_id          | balance_amount |

 +------+---------------------+----------------+

 |    1 | 6222000233022332111 |          18.90 |

 +------+---------------------+----------------+

 1 row in set (0.00 sec)

 root@zow 10:17:45>select * from t_zw1 where account_id=6222000233022332111;

 +------+---------------------+----------------+

 | id   | account_id          | balance_amount |

 +------+---------------------+----------------+

 |    1 | 6222000233022332111 |          18.90 |

 |    2 | 6222000233022332211 |         108.10 |

 |    3 | 6222000233022332311 |         180.30 |

 +------+---------------------+----------------+

 3 rows in set (0.00 sec)

 root@zow 10:18:59>select account_id, account_id+0.0, if(6222000233022332111=account_id, 1, 0) from t_zw1;

 +---------------------+----------------------+------------------------------------------+

 | account_id          | account_id+0.0       | if(6222000233022332111=account_id, 1, 0) |

 +---------------------+----------------------+------------------------------------------+

 | 6222000233022332111 | 6.222000233022332e18 |                                        1 |

 | 6222000233022332211 | 6.222000233022332e18 |                                        1 |

 | 6222000233022332311 | 6.222000233022332e18 |                                        1 |

 | 6222000233022334211 | 6.222000233022334e18 |                                        0 |

 | 6222000233022334311 | 6.222000233022334e18 |                                        0 |

 +---------------------+----------------------+------------------------------------------+

可以看出转化为float类型后,由于浮点类型精度的问题,红字的三条件记录转换后的值(约数)是一样的。

总结:隐式类型转换会带了很多不确定的结果,一定要杜绝where条件中隐式转换。

参考:https://dev.mysql.com/doc/refman/5.7/en/type-conversion.html

MySQL系列:隐式类型转化可能带来的坑的更多相关文章

  1. javascript中的隐式类型转化

    javascript中的隐式类型转化 #隐式转换 ## "+" 字符串和数字 如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+将进行拼接操作. 如果其中一个操作数是对 ...

  2. mysql的隐式转化

    MySQL隐式转化整理 前几天在微博上看到一篇文章:价值百万的 MySQL 的隐式类型转换感觉写的很不错,再加上自己之前也对MySQL的隐式转化这边并不是很清楚,所以就顺势整理了一下.希望对大家有所帮 ...

  3. C++中的显式类型转化

    类型转化也许大家并不陌生,int i; float j; j = (float)i; i = (int)j; 像这样的显式转化其实很常见,强制类型转换可能会丢失部分数据,所以如果不加(int)做强制转 ...

  4. Linq之隐式类型、自动属性、初始化器、匿名类

    目录 写在前面 系列文章 隐式类型 自动属性 初始化器 匿名类 总结 写在前面 上篇文章是本系列的小插曲,也是在项目中遇到,觉得有必要总结一下,就顺手写在了博客中,也希望能帮到一些朋友.本文将继续介绍 ...

  5. C#3.0新增功能03 隐式类型本地变量

    连载目录    [已更新最新开发文章,点击查看详细] 从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var. 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但 ...

  6. C#中的隐式类型var——详细示例解析

    从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,它的具体类型由编译器根据上下文推断而出. 下面就让我来总结下隐式类型的一些特点: 1.va ...

  7. .NET中那些所谓的新语法之一:自动属性、隐式类型、命名参数与自动初始化器

    开篇:在日常的.NET开发学习中,我们往往会接触到一些较新的语法,它们相对以前的老语法相比,做了很多的改进,简化了很多繁杂的代码格式,也大大减少了我们这些菜鸟码农的代码量.但是,在开心欢乐之余,我们也 ...

  8. C#隐式类型

    隐式类型 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sys ...

  9. C#语法糖之第一篇:自动属性&隐式类型

    今天给大家分享一下C#语法糖的简单的两个知识点吧. 自动属性:在 C# 4.0 和更高版本中,当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁. 客户端代码还可通过这些属性创建对象 ...

随机推荐

  1. Parallels Desktop 设置win网络连接

    目的: 1 虚拟机中的win系统技能访问外网 2 可以和Mac系统互联 首先来实现1,很简单: 打开控制中心对应系统的设置 选择[硬件]->[网络] 源:设置共享网络 到此就达到1目的了: 现在 ...

  2. design.js

    //模块式开发 var myNamespace = (function () { var myPrivateVar = 0; var myPrivateMethod = function (foo) ...

  3. oracle 删除用户命令和部分表空间操作

    删除用户 drop user user_name cascade; 建立表空间 CREATE TABLESPACE data01DATAFILE '/oracle/oradata/db/DATA01. ...

  4. bzoj 2301 [HAOI2011]Problem b(莫比乌斯反演+分块优化)

    题意:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 1≤n≤50000,1≤a≤b≤50000, ...

  5. [原创]java获取word文档的条目化内容

    在开发Web办公系统或文档系统时,PageOffice组件是众所周知的在线处理微软word/ppt/excel文档的强大工具,它对WORD文档的各种处理在API层面进行了封装,屏蔽了Office VB ...

  6. BlueSea笔记<1>--Cricket初探

    最近在看Cricket这个实现了Actor模式的F#开源框架,对其工作方式作了一番探究.首先来看一段简单的例子代码: type Say = | Hello let greeter = actor { ...

  7. 创建app前的环境配置/AppIcon/启动图片

    1.真机调试http://blog.csdn.net/tht2009/article/details/48580569 2.创建app前的环境配置

  8. 杂项:ASP.NET Core

    ylbtech-杂项:ASP.NET Core 1.返回顶部 1. ASP.NET Core 是一个跨平台的高性能开源框架,用于生成基于云且连接 Internet 的新式应用程序.使用 ASP.NET ...

  9. margin---bug

    常见的浏览器下margin出现的bug IE6中双边距Bug:发生场合:当给父元素内第一个浮动元素设置margin-left(元素float:left)或margin-right(元素float:ri ...

  10. MySQL主从详细安装步骤

    网站: 程序在:web服务器192.168.1.100上面 数据库在:MySQL服务器192.168.1.123上面 实现目的:增加一台MySQL备份服务器(192.168.1.124),作为MySQ ...