MySQL中隐式转换的示例分析

  介绍

这篇文章主要介绍MySQL中隐式转换的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

<强>一、问题描述

root@mysqldb 二二12:,,[xucl]祝辞,show  create  table  t1 \ G   * * * * * * * * * * * * * * * * * * * * * * * * * * *,1只row  * * * * * * * * * * * * * * * * * * * * * * * * * * *   ,,,,,,表:t1   Create 表:,Create  TABLE  t1, (   “id”,才能varchar (255), DEFAULT  NULL   ),引擎=InnoDB  DEFAULT  CHARSET=utf8   1,row  set 拷贝;(0.00,sec)      root@mysqldb  22:19:,, [xucl]祝辞,select  *,得到t1;   +--------------------+   |,id ,,,,,,,,,,,,,,, |   +--------------------+   |,204027026112927605 |   |,204027026112927603 |   |,2040270261129276,,|   |,2040270261129275,,|   |,100,,,,,,,,,,,,,,,|   |,101,,,,,,,,,,,,,,,|   +--------------------+   6,rows  set 拷贝;(0.00,sec)

奇怪的现象:

root@mysqldb  22:19:,, [xucl]祝辞,select  *,得到t1  where  id=204027026112927603;   +--------------------+   |,id ,,,,,,,,,,,,,,, |   +--------------------+   |,204027026112927605 |   |,204027026112927603 |   +--------------------+   2,rows  set 拷贝;(0.00,sec)

 MySQL中隐式转换的示例分析

<强>什么鬼,明明查的是204027026112927603,为什么204027026112927605也出来了

<强>二、源码解释

堆栈调用关系如下所示:

 MySQL中隐式转换的示例分析

其中<代码>加入::exec() 是执行的入口,<代码> Arg_comparator: compare_real() 是进行等值判断的函数,其定义如下

int  Arg_comparator: compare_real ()   {   ,/*   ,,,Fix  yet  another  manifestation  of 错误# 2338只& # 39;挥发性# 39;will 指导   ,,,gcc 用flush  double  values  out  of  80 - bit  Intel  FPU  registers 之前   ,,,performing 从而比较。   ,*/volatile 才能double  val1, val2;   val1才能=,(*)→val_real ();   if 才能;(! (*)→null_value)   {才能   ,,,val2=, (* b)→val_real ();   ,,,if  (! (* b)→null_value)   ,,,{   ,,,,,if  (set_null)   ,,,,,,,老板→null_value=https://www.yisu.com/zixun/0;   如果(val1 null_value=1;   返回1;   }

比较步骤如下图所示,逐行读取t1表的id列放入val1,而常量204027026112927603存在于缓存中,类型为两类型(2.0402702611292762 e + 17),所以到这里传值给val2后val2=2.0402702611292762 e + 17。

 MySQL中隐式转换的示例分析

当扫描到第一行时,204027026112927605转成双的值为2.0402702611292762 e17等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合

 MySQL中隐式转换的示例分析

如何检测字符串类型的数字转成双类型是否溢出呢?<强>这里经过测试,当数字超过16位以后,转成双类型就已经不准确了强,例如20402702611292711会表示成20402702611292712(如图中val1)

 MySQL中隐式转换的示例分析

 MySQL中隐式转换的示例分析

MySQL字符串转成双的定义函数如下:
{   char 才能buf [DTOA_BUFF_SIZE];   double 才能,res;   DBUG_ASSERT(才能最终获得!=,NULL ,,, ((str  !=, NULL ,,, *最终获得!=,NULL), | |   ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,(str ==, NULL ,,, *最终获得==,NULL)),,,   ,,,,,,,,,,,,,error  !=, NULL);      res=,才能my_strtod_int (str,,,,错误,,但,,sizeof (buf));   return 才能;(* error ==, 0), ?, res :, (res  & lt;, 0, ?, -DBL_MAX :, DBL_MAX);   }

真正转换函数<代码> my_strtod_int> MySQL中隐式转换的示例分析