MySQL隐式转换的示例分析

  介绍

这篇文章主要为大家展示了“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)   640年?wx_fmt=jpeg

 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 缓冲区(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位置在时差。c(太复杂了,简单贴个注释吧)

/*   ,strtod  for  IEEE - arithmetic 机器。   ,   ,却;能够strtod  returns  a  nearest  machine  number 用,input 小数   ,string (一、sets  errno 用EOVERFLOW)只Ties 断开连接;broken  by 从而IEEE 人   规则。   ,   ,Inspired  loosely  by  William  D只克林杰# 39;s  paper “请;用Read 浮动   ,Point  Numbers  Accurately" [Proc只ACM  SIGPLAN  & # 39; 90年,页只92 - 101]。   ,   ,修改:   ,   ,1只only 我方表示歉意require  IEEE  (not  IEEE  double-extended)。   ,2只get 我方表示歉意by  with  floating-point  arithmetic  a  case 拷贝   ,Clinger  missed ——, when 我们# 39;re  computing  d  * 10 ^ n   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null

MySQL隐式转换的示例分析