百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

MySQL 避坑指南之隐式数据类型转换

yuyutoo 2025-05-08 22:04 11 浏览 0 评论

作者 | 不剪发的Tony老师 责编 | 欧阳姝黎
出品 | CSDN博客

知之为知之,不知为不知,是知也。——《论语》

今天我们来聊聊 MySQL 中存在的隐式数据类型转换以及可能带来的问题。

当两个不同类型的数据进行运算时,为了使得它们能够兼容,MySQL 可能会执行隐式的数据类型转换。例如,MySQL 在需要时会自动将字符串转换为数字,反之亦然。

mysql> SELECT 1+'1'; -> 2mysql> SELECT CONCAT(2,' test'); -> '2 test'

我们也可使用 CAST() 函数将数字显式转换为字符串。CONCAT() 函数中的隐式类型转换是因为它只能接收字符串类型的参数。

mysql> SELECT 38.8, CAST(38.8 AS CHAR); -> 38.8, '38.8'mysql> SELECT 38.8, CONCAT(38.8); -> 38.8, '38.8'

以下是比较运算中的类型转换规则:

如果任意一个参数为 ,比较的结果为 ,<=> 相等比较运算符除外。 <=> 的运算结果为 true,不需要进行类型转换。

如果两个参数都是字符串,执行字符串比较。

如果两个参数都是整数,执行整数比较。

如果不是和数字进行比较,十六进制数值将被看作二进制字符串。

如果一个参数是 TIMESTAMP 或者 DATETIME 字段,另一个参数是常量,该常量将会在比较之前转换为时间戳类型。这一规则是为了更好地支持 ODBC 规范。IN() 运算符中的参数不会执行这一转换。为了保险起见,记得在执行比较运算时使用完整的日期时间、日期或者时间字符串。例如,在使用 BTWEEN 运算符判断日期或者时间数据时,利用 CAST() 函数将数据的类型显示转换成相应的类型。

返回单行结果的子查询不会被当作常量。例如,当一个返回整数的子查询和 DATETIME 数据进行比较时,DATETIME 将会被转换为整数类型,而不会将子查询的结果转换为时间类型。如果想要执行日期时间比较,可以使用 CAST() 函数显式将子查询的结果转换为 DATETIME 类型。

如果一个参数为精确数字类型(decimal),比较的方法取决于另一个参数的类型。如果另一个参数是精确数字或者整数类型,使用精确数字比较;如果另一个参数是浮点数类型,使用浮点数比较。

其他情况下,使用浮点数比较。例如,字符串和精确数字的比较使用浮点数比较方法。

关于时间类型之间的转换规则,可以参考官方文档。

以下示例演示了将字符串转换为数字的比较操作:

mysql> SELECT 1 > '6x'; -> 0mysql> SELECT 7 > '6x'; -> 1mysql> SELECT 0 > 'x6'; -> 0mysql> SELECT 0 = 'x6'; -> 1

如果将字符串类型的字段和数字进行比较,MySQL 无法使用该字段上的索引快速查找数据。例如,str_col 是一个索引字段,该索引无法用于以下语句:

SELECT * FROM tbl_name WHERE str_col=1;

问题的原因在于很多不同的字符串都可以转换为数字 1,例如’1’、’ 1’ 或者 ‘1a’。

浮点数和 INTEGER 类型的超大数值之间的比较是近似比较,因为整数在比较之前需要转换为双精度浮点数,双精度浮点数无法精确地表示所有的 64 位整数。例如,整数 253 + 1 无法使用浮点数进行表示,只能近似为 253 或者 253 + 2。

举例来说,以下只有第一个比较运算中的两个值相等,但是两个比较运算都返回了 true(1):

mysql> SELECT '9223372036854775807' = 9223372036854775807; -> 1mysql> SELECT '9223372036854775807' = 9223372036854775806; -> 1

字符串转换为浮点数与整数转换为浮点数的方式可能不同。整数可能使用 CPU 转换为浮点数,而字符串可能使用浮点数乘法进行逐位转换。另外,转换结果可能受到各种因素的影响,例如计算机的架构、编译器版本或者优化级别等。避免这种问题的方法之一就是使用 CAST() 函数,这样数据就不会被隐式转换为浮点数。

mysql> SELECT CAST('9223372036854775807' AS UNSIGNED) = 9223372036854775806; -> 0
关于浮点数比较的更多信息,可以参考官方文档。

MySQL 服务器提供了一个转换库 dtoa,可以支持字符串或者 DECIMAL 数据和近似数字(FLOAT/DOUBLE)之间的基本转换功能:

跨平台的一致性转换结果,例如,可以消除 Unix 和 Windows 之间的差异。

可以精确表示之前无法提供足够精度的数据,例如接近 IEEE 限制的数据。

以尽可能高的精度将数字转换成字符串格式。dtoa 的精度总是等于或者高于标准 C 代码库函数。

数字或者时间类型到字符串的隐式转换结果的字符集和排序规则取决于 character_set_connection 和 collation_connection 系统变量。(这些变量通常使用 SET NAMES 进行设置。关于连接的字符集的信息,可以参考官方文档。)

这意味着这种转换的结果是一个非二进制的字符串(CHAR、VARCHAR 或者 LONGTEXT),除非连接字符集被设置为 binary。此时,转换结果是一个二进制字符串(BINARY、VARBINARY 或者 LONGBLOB)。

对于整数类型的表达式,前文所述的表达式求值和表达式赋值有所不同。例如以下语句:

CREATE TABLE t SELECT integer_expr;

这种情况下,表 t 的字段类型取决于整数表达式的长度,可能是 INT 或者 BIGINT。如果表达式的最大长度超过了 INT,使用 BIGINT 类型。这就意味着我们可以通过一个足够长的表达式创建 BIGINT 类型的字段:

CREATE TABLE t SELECT 000000000000000000000 AS col;
DESC t;Field|Type ||Key|Default|Extra|-----+------+----+---+-------+-----+col |bigint|NO | |0 | |

JSON 数据的比较分为两种情况。第一层次的比较基于被比较数据的 JSON 类型,如果两个类型不同,比较的结果取决于具有更高优先级的类型;如果两个数据的 JSON 类型相同,使用具体的类型规则进行第二层次的比较。对于 JSON 和非 JSON 数据的比较,先将非 JSON 数据转换为 JSON 类型,然后进行比较。详细信息可以参考官方文档。

作者简介:不剪发的 Tony 老师,CSDN 博客专家,CSDN 学院签约讲师, GitChat 专栏作者。十余年数据库管理与开发经验。目前在一家全球性的游戏公司从事数据库架构设计和开发工作,擅长各种数据库管理与 SQL 开发,拥有Oracle OCP 和 Redhat RHCE 证书。


相关推荐

IntelliJ IDEA插件开发(java开发idea插件)

引言IntelliJIDEA是JetBrains公司开发的一款广受欢迎的集成开发环境(IDE)。它不仅支持Java等多种编程语言,还通过插件系统提供了强大的扩展能力。本分享旨在介绍如何使用Java开...

如何验证自己的idea或者如何产生idea?小编教你如何检索……

申请专利前首先要做的是检索查重,如果你的构思已经被别人申请过专利,那么就不符合专利“新颖性”的要求。因此,如果你有了idea之后如何验证自己的idea具备新颖性,或者如何产生idea呢?今天,小编带着...

idea激活码失效了,这样解决,稳定使用!

最近官网封控比较严格,正式版激活码是不是又掉线了?掉线请看这里,这里有一个解决的方法,就是让工具不联网就可以继续使用激活码了。激活码本来就叫离线激活码,现在要怎么使id工具不联网?·可以打开这里帮助,...

5分钟解决 IntelliJ IDEA 使用问题(免费激活至 2100 年)

直接进入正题!效果安装1.官网下载idea...

【中高级前端必看】- 结合代码实践,全面学习前端工程化

前言前端工程化,简而言之就是软件工程+前端,以自动化的形式呈现。就个人理解而言:前端工程化,从开发阶段到代码发布生产环境,包含了以下几个内容:开发构建测试部署...

Android绘制流程(android界面绘制)

Android绘制流程来源:极客头条MFC、WTL、DuiLib、QT、Skia、OpenGL。Android里面的画图分为2D和3D两种:2D是由Skia来实现的,3D部分是由OpenGL实现...

ExpandListView 的一种巧妙写法(g的另一种写法上下两个圈连起来怎么打)

ExpandListView大家估计也用的不少了,一般有需要展开的需求的时候,大家不约而同的都想到了它然后以前自己留过记录的一般都会找找以前自己的代码,没有记录习惯的就会百度、谷歌,这里吐槽一下,好几...

通过圆形载入View了解自定义View(圆形div怎么搞)

这是自定义View的第一篇文章,通过制作简单的自定义View来了解自定义View的流程。自定义View是Android学习和开发中必不可少的一部分。通过自定义View我们可以制作丰富绚丽的控件,自定...

鸿蒙开源第三方组件——自定义流式布局组件FlowLayout_ohos

前言基于安卓平台的自定义流式布局组件FlowLayout(https://blog.csdn.net/fzhhsa/article/details/103003019),实现了鸿蒙的功能化迁移和重构...

「经典总结」一个View,从无到有会走的三个流程,你知道吗?

...

手把手带你写FlowLayout(流式布局)

流式布局在android中主要应用在搜索记录和用户标签,下面是效果图首先我们分析流式布局的原理。其实就是当一个子view加上之前的子view的宽度超过了父容器的宽度的时候就换行。接下来我们手把手书写流...

Android View(android view使用mvvm架构)

AndroidUI界面架构每个Activity包含一个PhoneWindow对象,PhoneWindow设置DecorView为应用窗口的根视图,在里面就是TitleView和ContentView...

《教你步步为营掌握自定义View》一文读后感

今天读了简书作者[milter]的一篇文章《教你步步为营掌握自定义View》,大有裨益。作者以幽默风趣、通俗易懂的大白话一步步讲述了View的来龙去脉,甚是详尽,实属自定义View文集中的一篇非常优秀...

Android面试官:你究竟有多大的勇气,在简历上写了“精通”?

所周知,简历上“了解=听过名字;熟悉=知道是啥;熟练=用过;精通=做过东西”。最近在面试,我现在十分后悔在简历上写了“精通”二字…先给大家看看我简历上的技能清单:良好的java基础,熟悉掌握面向对象思...

iOS 视图---动画渲染机制探究(动画渲染用哪个软件最好)

腾讯Bugly特约作者:陈向文终端的开发,首当其冲的就是视图、动画的渲染,切换等等。用户使用App时最直接的体验就是这个界面好不好看,动画炫不炫,滑动流不流畅。UI就是App的门面,它的体验伴...

取消回复欢迎 发表评论: