数据库MySQL基础入门之MySQL隐式转换

news2025/1/21 3:01:27

一、问题描述

root@mysqldb 22:12: [xucl]> show create table t1\G

*************************** 1. row ***************************

   Table: t1

Create Table: CREATE TABLE t1 (

id varchar(255) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8

1 row in set (0.00 sec)

root@mysqldb 22:19: [xucl]> select * from t1;

±-------------------+

| id |

±-------------------+

| 204027026112927605 |

| 204027026112927603 |

| 2040270261129276 |

| 2040270261129275 |

| 100 |

| 101 |

±-------------------+

6 rows in set (0.00 sec)

奇怪的现象:

root@mysqldb 22:19: [xucl]> select * from t1 where id=204027026112927603;

±-------------------+

| id |

±-------------------+

| 204027026112927605 |

| 204027026112927603 |

±-------------------+

2 rows in set (0.00 sec)

640?wx_fmt=jpeg

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

二、源码解释

堆栈调用关系如下所示:
IMG_256
其中JOIN::exec()是执行的入口,Arg_comparator::compare_real()是进行等值判断的函数,其定义如下

int Arg_comparator::compare_real()

{

/*

Fix yet another manifestation of Bug#2338. 'Volatile' will instruct

gcc to flush double values out of 80-bit Intel FPU registers before

performing the comparison.

*/

volatile double val1, val2;

val1= (*a)->val_real();

if (!(*a)->null_value)

{

val2= (*b)->val_real();

if (!(*b)->null_value)

{

  if (set_null)

    owner->null_value= 0;

  if (val1 < val2)  return -1;

  if (val1 == val2) return 0;

  return 1;

}

}

if (set_null)

owner->null_value= 1;

return -1;

}

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

IMG_257
当扫描到第一行时,204027026112927605转成doule的值为2.0402702611292762e17,等式成立,判定为符合条件的行,继续往下扫描,同理204027026112927603也同样符合
IMG_258
如何检测string类型的数字转成doule类型是否溢出呢?这里经过测试,当数字超过16位以后,转成double类型就已经不准确了,例如20402702611292711会表示成20402702611292712(如图中val1)
IMG_259
IMG_260
MySQL string转成double的定义函数如下:

{

char buf[DTOA_BUFF_SIZE];

double res;

DBUG_ASSERT(end != NULL && ((str != NULL && *end != NULL) ||

                          (str == NULL && *end == NULL)) &&

          error != NULL);

res= my_strtod_int(str, end, error, buf, sizeof(buf));

return (*error == 0) ? res : (res < 0 ? -DBL_MAX : DBL_MAX);

}

真正转换函数my_strtod_int位置在dtoa.c(太复杂了,简单贴个注释吧)

/*

strtod for IEEE–arithmetic machines.

This strtod returns a nearest machine number to the input decimal

string (or sets errno to EOVERFLOW). Ties are broken by the IEEE round-even

rule.

Inspired loosely by William D. Clinger’s paper "How to Read Floating

Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101].

Modifications:

  1. We only require IEEE (not IEEE double-extended).

  2. We get by with floating-point arithmetic in a case that

 Clinger missed -- when we're computing d * 10^n

 for a small integer d and the integer n is not too

 much larger than 22 (the maximum integer k for which

 we can represent 10^k exactly), we may be able to

 compute (d*10^k) * 10^(e-k) with just one roundoff.
  1. Rather than a bit-at-a-time adjustment of the binary
 result in the hard case, we use floating-point

 arithmetic to determine the adjustment to within

 one bit; only in really hard cases do we need to

 compute a second residual.
  1. Because of 3., we don’t need a large table of powers of 10
 for ten-to-e (just some small tables, e.g. of 10^k

 for 0 <= k <= 22).

*/

既然是这样,我们测试下没有溢出的案例

root@mysqldb 23:30: [xucl]> select * from t1 where id=2040270261129276;

±-----------------+

| id |

±-----------------+

| 2040270261129276 |

±-----------------+

1 row in set (0.00 sec)

root@mysqldb 23:30: [xucl]> select * from t1 where id=101;

±-----+

| id |

±-----+

| 101 |

±-----+

1 row in set (0.00 sec)

结果符合预期,而在本例中,正确的写法应当是

root@mysqldb 22:19: [xucl]> select * from t1 where id=‘204027026112927603’;

±-------------------+

| id |

±-------------------+

| 204027026112927603 |

±-------------------+

1 row in set (0.01 sec)

三、结论

避免发生隐式类型转换,隐式转换的类型主要有字段类型不一致、in参数包含多个类型、字符集类型或校对规则不一致等

隐式类型转换可能导致无法使用索引、查询结果不准确等,因此在使用时必须仔细甄别

数字类型的建议在字段定义时就定义为int或者bigint,表关联时关联字段必须保持类型、字符集、校对规则都一致

文章来源:网络 版权归原作者所有

上文内容不用于商业目的,如涉及知识产权问题,请权利人联系小编,我们将立即处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151928.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArcGIS基础实验操作100例--实验74灾害影响缓冲区分析

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验74 灾害影响缓冲区分析 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;…

剑指offer----C语言版----第十四天

表示数值的字符串 原题链接&#xff1a;剑指 Offer 20. 表示数值的字符串 - 力扣&#xff08;LeetCode&#xff09;1.1 题目描述 请实现一个函数用来判断字符串是否表示数值&#xff08;包括整数和小数&#xff09;。数值&#xff08;按顺序&#xff09;可以分成以下几个部分&a…

常见胶片的分类和结构

胶片的分类方法非常多&#xff0c;本质上属于高分子材料范畴&#xff0c;很多类别已经超出笔者的认知范围&#xff0c;我们只对与档案数字资源长期保存和异质备份相关的胶片分类方法进行介绍。笔者整理了十大分类如下图所示&#xff1a; 各分类简要介绍 1. 按宽度尺寸分类 常…

【Linux】进程信号万字详解(上)

&#x1f387;Linux&#xff1a; 博客主页&#xff1a;一起去看日落吗分享博主的在Linux中学习到的知识和遇到的问题博主的能力有限&#xff0c;出现错误希望大家不吝赐教分享给大家一句我很喜欢的话&#xff1a; 看似不起波澜的日复一日&#xff0c;一定会在某一天让你看见坚持…

194: vue+openlayers 根据卫星lat,lon,alt,俯仰角,方位角,绘制地面的拍摄的区域

第194个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers项目中研究卫星的拍摄范围。 根据卫星的高度,经度,纬度,方位角,俯仰角以及拍摄的幅宽,幅长等参数,绘制拍摄的矩形框和中心点。这里用到了一些公式,参考代码,尤其是大部分使用的是弧度而非角度,需…

青铜到王者,8本最好的Python从入门到进阶的书

春节长假还有1周了&#xff0c;是时候囤一些书充充电了&#xff01;新的一年群里很多小伙伴开始想学Python&#xff0c; 无论是准备转行的&#xff0c;还是想多学一份技能提高职场竞争力的&#xff0c;都想选择Python赛道&#xff0c;下面给大家推荐一些非常不错的Python入门到…

联合证券|利好叠加有望实质兑现 机构加码布局装修建材

组织加码布局装饰建材板块。据了解&#xff0c;受房地产利好方针带动、职业竞赛格式持续改进及原材料本钱下降等多重利好叠加&#xff0c;装饰建材板块有望迎来实质性利好&#xff0c;虽然曩昔两个多月来相关公司有所反弹&#xff0c;但组织以为行情仍然在路上。 多重利好推进 …

架构设计---高可用的处理

前言&#xff1a; 系统的高可用架构就是要在上述各种故障情况下&#xff0c;保证系统依然可用提供服务&#xff0c;具体包括以下几种架构方案。 冗余备份&#xff1a; 各种服务器故障是不可避免的&#xff0c;架构设计上就要保证&#xff0c;当服务器故障的时候&#xff0c;…

简短通俗理解动态规划算法--最短路径问题

问题&#xff1a;从某顶点出发&#xff0c;沿图的边到达另一顶点所经过的路径中&#xff0c;各边上权值之和最小的一条路径——最短路径。在博客动态规划算法中介绍了动态规划的基本思想已经建立动态规划模型的步骤&#xff0c;下面将其中的方法分析最短路径问题。 最短路径有…

CBAM: Convolutional Block Attention Module

https://arxiv.org/pdf/1807.06521.pdf 摘要&#xff1a; 我们提出了卷积块注意模块(CBAM)&#xff0c;一个简单而有效的用于前馈卷积神经网络的注意模块。给定中间特征图&#xff0c;我们的模块依次推导出沿通道和空间两个独立维度的注意图&#xff0c;然后将注意图乘到输入…

vue-seamless-scroll数据量少时,暂停滚动,继续滚动

需求内容 大屏项目&#xff1a;指定dom元素内&#xff0c;如果子元素内容过多&#xff0c;超出父元素的最高高度&#xff0c;可以发生自动滚动&#xff1b;如果子元素内容没有超出父元素的最高高度&#xff0c;不可以发生自动滚动。 . 实现方案 获取数据后并渲染到dom后&am…

并查集的查询与合并详解

文章目录 一、并查集的概念 二、并查集的实现 2、1 并查集不同集合&#xff08;树&#xff09;的形成 2、2 find&#xff08;&#xff09;函数找一个元素集合的编号&#xff08;元素所属于树的祖宗&#xff09; 2、3 合并两个不同集合&#xff08;合并两棵不同的树&#xff09…

SpringCloud学习笔记 - Nacos集群配置和配置持久化

1. 集群架构 要组成集群Nacos必须要有3个或以上的Nacos服务节点&#xff0c;官网推荐在生产服务中使用集群架构。 官网对Nacos集群架构的说明&#xff1a;https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html 总体来说有三种方式可以实现Nacos集群部署&#xff1a; …

恒远模式(flyweight)

简介&#xff1a;共享对象&#xff0c;当一个对象可以被多次利用的时候&#xff0c;并且对象内部相同&#xff0c;这个时候需要考虑让对象进行复用&#xff0c;而不是多次创建结构图&#xff1a;代码就不写了&#xff0c;因为我觉得这东西没啥用&#xff0c;因为一个对象对应的…

技术分享 | 测试平台开发-前端开发之Vue.js 框架

Vue.js 是一套用于构建用户界面的渐进式框架&#xff0c;在目前的前端开放中比较流行的前端框架。Vue 被设计成自底向上的逐层应用。Vue 的核心库只关注视图层&#xff0c;不仅易于上手&#xff0c;还便于与第三方库或已有项目整合。但是学习 Vue.js 需要一定的 HTML、CSS、和 …

指针进阶(3)

tips 1. sizeof的返回类型时size_t。size_t就是为sizeof量身定做的&#xff0c;size_t就是unsigned int 2. strlen碰到\0会停下来&#xff0c;而sizeof则不会&#xff0c;也将其算作一个字符 3. 要注意这么两对东西&#xff1a; scanf()与gets(): \0 , \n , 空格 …

<TCP网络编程>——《计算机网络》

目录 1.TCP网络程序 1.1 TCP socket API 1.1.1 socket(): 1.1.2 bind():​ 1.1.3 listen(): ​ 1.1.4 accept(): 1.1.5 connect(): 2. 封装 TCP socket 2.1 实现一个简单的英译汉的功能 3.简单的TCP网络程序(多进程版本) 4. 简单的TCP网络程序(多线程版本) 5. 线程…

SpringBoot自定义MessageConvert

目录 前言 原理 实现 拓展 前言 对于页面携带的请求头中的AcceptSpringBoot有对应的10种MessageConvert可以支持写出对应的媒体类型&#xff0c;比如application/xml、application/json…… 我们还可以通过向容器放入一个WebMvcConfigurer 实现定制化SpingMVC&#xff0…

Android 深入系统完全讲解(7)

7 如何调试代码&#xff0c;JNI&#xff0c;Framework,APP 调试技巧是我在每入职一家新公司&#xff0c;都会给大家分享的。在 MTK 官方培训还是需要编译才能调试的时候&#xff0c;我无意中调试 MMS 代码&#xff0c;发现跟进了系统代码&#xff0c;调试了相关的匹配搜索子串代…

Java多线程(一)——Hotspot的锁( Synchronized)

1. 锁的概念 Java语言为了解决并发编程中存在的原子性、可见性和有序性问题&#xff0c;提供了一系列和并发处理相关的关键字&#xff0c;比如synchronized、volatile、final、concurren包等 2. Synchronized的基本使用 synchronized是Java提供的一个并发控制的关键字。主要…