本文摘自PHP中文网,作者coldplay.xixi,侵删。
mysql教程栏目介绍相关的隐式转换更多相关免费学习推荐:mysql教程(视频)
一、问题描述
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
奇怪的现象:
1 2 3 4 5 6 7 8 |
|
什么鬼,明明查的是204027026112927603,为什么204027026112927605也出来了
二、源码解释
堆栈调用关系如下所示:
其中JOIN::exec()
是执行的入口,Arg_comparator::compare_real()
是进行等值判断的函数,其定义如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
比较步骤如下图所示,逐行读取t1表的id列放入val1,而常量204027026112927603存在于cache中,类型为double类型(2.0402702611292762E+17),所以到这里传值给val2后val2=2.0402702611292762E+17。
当扫描到第一行时,204027026112927605转成doule的值为2.0402702611292762e17,等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合
如何检测string类型的数字转成doule类型是否溢出呢?这里经过测试,当数字超过16位以后,转成double类型就已经不准确了,例如20402702611292711会表示成20402702611292712(如图中val1)
MySQL string转成double的定义函数如下:
1 2 3 4 5 6 7 8 9 10 |
|
真正转换函数my_strtod_int
位置在dtoa.c(太复杂了,简单贴个注释吧)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
既然是这样,我们测试下没有溢出的案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
结果符合预期,而在本例中,正确的写法应当是
1 2 3 4 5 6 7 |
|
三、结论
避免发生隐式类型转换,隐式转换的类型主要有字段类型不一致、in参数包含多个类型、字符集类型或校对规则不一致等
隐式类型转换可能导致无法使用索引、查询结果不准确等,因此在使用时必须仔细甄别
数字类型的建议在字段定义时就定义为int或者bigint,表关联时关联字段必须保持类型、字符集、校对规则都一致
最后贴一下官网对于隐式类型转换的说明吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
以上就是看看 MySQL令人咋舌的隐式转换的详细内容,更多文章请关注木庄网络博客!
相关阅读 >>
mariadb(mysql)创建、删除、选择及数据类型使用详解
更多相关阅读请进入《mysql》频道 >>
数据库系统概念 第6版
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。