MySQL系列:隐式类型转化可能带来的坑
在开发规范中,我们往往会要求研发避免在where条件中出现隐式类型转换,这么要求大概有以下两方面的原因:
- 隐式类型转换可能导致索引失效;
- 隐式类型转换可能产生非预期的结果。
注:这里说的是隐式类型转换。
我们可以看下官方关于类型转换的解释:
这里讨论以下情况:
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系列:隐式类型转化可能带来的坑的更多相关文章
- javascript中的隐式类型转化
javascript中的隐式类型转化 #隐式转换 ## "+" 字符串和数字 如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+将进行拼接操作. 如果其中一个操作数是对 ...
- mysql的隐式转化
MySQL隐式转化整理 前几天在微博上看到一篇文章:价值百万的 MySQL 的隐式类型转换感觉写的很不错,再加上自己之前也对MySQL的隐式转化这边并不是很清楚,所以就顺势整理了一下.希望对大家有所帮 ...
- C++中的显式类型转化
类型转化也许大家并不陌生,int i; float j; j = (float)i; i = (int)j; 像这样的显式转化其实很常见,强制类型转换可能会丢失部分数据,所以如果不加(int)做强制转 ...
- Linq之隐式类型、自动属性、初始化器、匿名类
目录 写在前面 系列文章 隐式类型 自动属性 初始化器 匿名类 总结 写在前面 上篇文章是本系列的小插曲,也是在项目中遇到,觉得有必要总结一下,就顺手写在了博客中,也希望能帮到一些朋友.本文将继续介绍 ...
- C#3.0新增功能03 隐式类型本地变量
连载目录 [已更新最新开发文章,点击查看详细] 从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var. 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但 ...
- C#中的隐式类型var——详细示例解析
从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,它的具体类型由编译器根据上下文推断而出. 下面就让我来总结下隐式类型的一些特点: 1.va ...
- .NET中那些所谓的新语法之一:自动属性、隐式类型、命名参数与自动初始化器
开篇:在日常的.NET开发学习中,我们往往会接触到一些较新的语法,它们相对以前的老语法相比,做了很多的改进,简化了很多繁杂的代码格式,也大大减少了我们这些菜鸟码农的代码量.但是,在开心欢乐之余,我们也 ...
- C#隐式类型
隐式类型 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Sys ...
- C#语法糖之第一篇:自动属性&隐式类型
今天给大家分享一下C#语法糖的简单的两个知识点吧. 自动属性:在 C# 4.0 和更高版本中,当属性的访问器中不需要其他逻辑时,自动实现的属性可使属性声明更加简洁. 客户端代码还可通过这些属性创建对象 ...
随机推荐
- luogu3379 【模板】最近公共祖先(LCA) 倍增法
题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...
- HDU1358 Period —— KMP 最小循环节
题目链接:https://vjudge.net/problem/HDU-1358 Period Time Limit: 2000/1000 MS (Java/Others) Memory Lim ...
- java24点算法
输入任意的四个数,求出所有能得到二十四点的算式,不过我是菜鸟,可能性能方面不好,希望各位多多指教1. [代码][Java]代码 import java.util.ArrayList;impo ...
- 官网下载java相关资源
官网下载java相关资源 官网地址:http://www.oracle.com 一.下载JDK 1.首先进入Downloads >> Java For Developers,如图 2.点击 ...
- IOS AutoLayout 代码实现约束—VFL
在autolayout下,尽管使用IB来拖放控件,但仍然避免不了用代码来创建控件,这是约束需要代码来实现. IOS 提供了两种添加约束的方法 第一种: +(instancetype)constrain ...
- gunicorn启动django时静态文件的加载
目前在用nginx+gunicorn对django进行部署 当我用gunicorn -w 4 -b 127.0.0.1:8080 myproject.wsig:application启动django时 ...
- 高可用性和PyMongo
High Availability and PyMongo高可用性和PyMongo************************************ PyMongo makes it e ...
- bzoj3143游走——期望+高斯消元
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3143 只需算出每条边被经过的概率,将概率从小到大排序,从大到小编号,就可得到最小期望: 每条 ...
- leetcode 字符串动态规划总结
问题1:leetcode 正则表达式匹配 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配 ...
- Bootstrap-CL:按钮下拉菜单
ylbtech-Bootstrap-CL:按钮下拉菜单 1.返回顶部 1. Bootstrap 按钮下拉菜单 本章将讲解如何使用 Bootstrap class 向按钮添加下拉菜单.如需向按钮添加下拉 ...