MySQL中的隐式转换(Implicit Conversion)

MySQL中的隐式转换(Implicit Conversion)指的是在SQL语句的执行过程中,数据库管理系统(DBMS)自动进行的数据类型转换。这种转换通常发生在数据类型不匹配但需要进行比较、计算或赋值等操作时。

以下是一些关于MySQL隐式转换的常见场景和注意事项:

1、字符串和数字之间的转换:

当字符串和数字进行算术运算时,字符串会被尝试转换为数字(如果可能)。例如,‘110’ + 10086会被解释为 110 + 10086。但是,如果字符串不能被解析为一个有效的数字(例如 ‘cba’ + 886),结果将为 886。
当字符串和数字进行比较时,也会发生类似的转换。

(test@192.168.80.230)[(none)]> select '110' + 10086;
+---------------+
| '110' + 10086 |
+---------------+
|         10196 |
+---------------+
1 row in set (0.00 sec)(test@192.168.80.230)[(none)]> select 'cba' + 886 as v1,'abc' + 886 as v2;
+-----+-----+
| v1  | v2  |
+-----+-----+
| 886 | 886 |
+-----+-----+
1 row in set, 2 warnings (0.00 sec)(test@192.168.80.230)[(none)]> select cast('1000000860000094443' as DECIMAL) as v1,cast('1000000860000094443' as DECIMAL(64,0)) as v2;
+------------+---------------------+
| v1         | v2                  |
+------------+---------------------+
| 9999999999 | 1000000860000094443 |
+------------+---------------------+
1 row in set, 1 warning (0.00 sec)

1.1、问题复现

创建测试表,并插入测试数据

create table T_Implicit_Conversion
(id int primary key,c_str1 varchar(64),c_str2 varchar(64),c_num DECIMAL(64,0) );insert into T_Implicit_Conversion
select 1,'10004100011000510085','cba',10004100011000510085
union all 
select 2,'10004100011000510084','nba',10004100011000510084;
union all 
select 3,'10004100011000510086','123',10004100011000510086
union all 
select 4,'10004100011000510087','aaa',10004100011000510087;
commit;
select * from T_Implicit_Conversion;(root@localhost)[db01]> select * from T_Implicit_Conversion;
+----+----------------------+--------+----------------------+
| id | c_str1               | c_str2 | c_num                |
+----+----------------------+--------+----------------------+
|  1 | 10004100011000510085 | cba    | 10004100011000510085 |
|  2 | 10004100011000510084 | nba    | 10004100011000510084 |
|  3 | 10004100011000510086 | 123    | 10004100011000510086 |
|  4 | 10004100011000510087 | aaa    | 10004100011000510087 |
+----+----------------------+------+------------------------+-- where条件字段类型和查询值类型一致的情况下(root@localhost)[db01]> select * from  T_Implicit_Conversion where c_str1 = '10004100011000510086';
+----+----------------------+--------+----------------------+
| id | c_str1               | c_str2 | c_num                |
+----+----------------------+------+------------------------+
|  3 | 10004100011000510086 | 123    | 10004100011000510086 |
+----+----------------------+--------+----------------------+
1 row in set (0.00 sec)

条件字段类型和查询值类型不一致的情况下,查询条件是 where str1 = 10004100011000510086

(root@localhost)[db01]> select * from T_Implicit_Conversion where c_str1=10004100011000510084;
+----+----------------------+--------+----------------------+
| id | c_str1               | c_str2 | c_num                |
+----+----------------------+--------+----------------------+
|  1 | 10004100011000510085 | cba    | 10004100011000510085 |
|  2 | 10004100011000510084 | nba    | 10004100011000510084 |
|  3 | 10004100011000510086 | 123    | 10004100011000510086 |
|  4 | 10004100011000510087 | aaa    | 10004100011000510087 |
+----+----------------------+------+------------------------+
4 rows in set (0.00 sec)

执行结果如上 10004100011000510084、5、7 的数据也跟着查出来了

1.2、分析原因

explain select * from  T_Implicit_Conversion where str1 = 10004100011000510086;   -- 查询结果不符合预期结果,不会产生warnings  
show warnings;

查看官方文档,可以得到字符型与数值型比较,最终都转化为浮点型来比较, 表字段为字符型,where查询值为数值型,可以转换,但会丢失精度,导致转换后数据丢失精度,查询不是预取的结果

(root@localhost)[db01]> select cast('10004100011000510084' as DECIMAL) as v1,cast('10004100011000510085' as DECIMAL) as v2,cast('10004-> ;
+------------+------------+------------+------------+
| v1         | v2         | v3         | v4         |
+------------+------------+------------+------------+
| 9999999999 | 9999999999 | 9999999999 | 9999999999 |
+------------+------------+------------+------------+
1 row in set, 4 warnings (0.01 sec)(root@localhost)[db01]> select cast('10004100011000510084' as float) as v1,cast('10004100011000510085' as float) as v2,cast('10004100011000510086' as float) as v3,cast('10004100011000510087 ' as float(10)) as v4;
+------------+------------+------------+------------+
| v1         | v2         | v3         | v4         |
+------------+------------+------------+------------+
| 1.00041e19 | 1.00041e19 | 1.00041e19 | 1.00041e19 |
+------------+------------+------------+------------+
1 row in set (0.00 sec)

1.3、表字段为字符型,内容较短时,可以转换,但不存在丢失精度的情况

(root@localhost)[db01]> create table T_Implicit_Conversion_2-> (id int primary key,->  c_str1 varchar(64),->  c_str2 varchar(64),->  c_num DECIMAL(18,2) ->  );
Query OK, 0 rows affected (0.03 sec)(root@localhost)[db01]> insert into T_Implicit_Conversion_2-> select 1,'100010086','cba',1000400510084-> union all-> select 2,'100010087','abc',1000400510085-> union all-> select 3,'100010088','nba',1000400510086-> union all -> select 4,'100010089','fba',1000400510087;
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0(root@localhost)[db01]> commit;
Query OK, 0 rows affected (0.00 sec)(root@localhost)[db01]> select * from T_Implicit_Conversion_2;
+----+-----------+--------+------------------+
| id | c_str1    | c_str2 | c_num            |
+----+-----------+--------+------------------+
|  1 | 100010086 | cba    | 1000400510084.00 |
|  2 | 100010087 | abc    | 1000400510085.00 |
|  3 | 100010088 | nba    | 1000400510086.00 |
|  4 | 100010089 | fba    | 1000400510087.00 |
+----+-----------+--------+------------------+
4 rows in set (0.00 sec)(root@localhost)[db01]> select * from T_Implicit_Conversion_2 where c_str1=100010086;
+----+-----------+--------+------------------+
| id | c_str1    | c_str2 | c_num            |
+----+-----------+--------+------------------+
|  1 | 100010086 | cba    | 1000400510084.00 |
+----+-----------+--------+------------------+
1 row in set (0.00 sec)(root@localhost)[db01]> select * from T_Implicit_Conversion_2 where c_str1='100010086';
+----+-----------+--------+------------------+
| id | c_str1    | c_str2 | c_num            |
+----+-----------+--------+------------------+
|  1 | 100010086 | cba    | 1000400510084.00 |
+----+-----------+--------+------------------+
1 row in set (0.00 sec)

官方文档地址
https://dev.mysql.com/doc/refman/8.0/en/type-conversion.html

1.4、表字段为数值型,where查询值为字符串

-- 表字段为数值型,where查询值为字符串 ,warnings Truncated incorrect DOUBLE value
(root@localhost)[db01]>  select * from T_Implicit_Conversion where id='2f';
+----+-----------+--------+------------------+
| id | c_str1    | c_str2 | c_num            |
+----+-----------+--------+------------------+
|  2 | 100010087 | abc    | 1000400510085.00 |
+----+-----------+--------+------------------+
1 row in set, 1 warning (0.00 sec)(root@localhost)[db01]> show warnings;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: '2f' |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)-- 表字段为数值型,where查询值为数值型 ,warnings 无内容
(root@localhost)[db01]> select * from T_Implicit_Conversion where id=2;
+----+-----------+--------+------------------+
| id | c_str1    | c_str2 | c_num            |
+----+-----------+--------+------------------+
|  2 | 100010087 | abc    | 1000400510085.00 |
+----+-----------+--------+------------------+
1 row in set (0.00 sec)(root@localhost)[db01]> show warnings;
Empty set (0.00 sec)

2、日期/时间类型和其他类型的转换:

当日期/时间类型与字符串或数字进行比较或计算时,可能会进行隐式转换。但是,这种转换的结果可能并不总是符合预期,因此最好显式地进行转换或使用适当的函数。

3、NULL值的处理:

在MySQL中,NULL 是一个特殊的值,表示“无”或“未知”。当 NULL 参与算术运算时,结果通常为 NULL。当 NULL 与其他值进行比较时,结果也通常是 NULL(除了 IS NULL 和 IS NOT NULL 这样的比较)。

(root@localhost)[db01]> select null + 886;
+------------+
| null + 886 |
+------------+
|       NULL |
+------------+
1 row in set (0.00 sec)(root@localhost)[db01]> select null + 'nba';
+--------------+
| null + 'nba' |
+--------------+
|         NULL |
+--------------+
1 row in set, 1 warning (0.00 sec)

4、整数和小数之间的转换:

整数和小数(即DECIMAL、FLOAT、DOUBLE等)之间的转换通常是自动的,但可能会导致精度损失或舍入。

In standard SQL, the syntax DECIMAL(M) is equivalent to DECIMAL(M,0). Similarly, the syntax DECIMAL is equivalent to DECIMAL(M,0), where the implementation is permitted to decide the value of M. MySQL supports both of these variant forms of DECIMAL syntax. The default value of M is 10.

在标准SQL中,语法DECIMAL(M)等效于DECIMAL的(M,0)。类似地,语法DECIMAL等效于DECIMAL(M,0),其中允许实现来决定M的值。MySQL支持这两种形式的DECIMAL语法。M的默认值为10。

(test@192.168.80.230)[(none)]> select cast('1000000860000094443' as DECIMAL) as v1,cast('1000000860000094443' as DECIMAL(64,0)) as v2;
+------------+---------------------+
| v1         | v2                  |
+------------+---------------------+
| 9999999999 | 1000000860000094443 |
+------------+---------------------+
1 row in set, 1 warning (0.00 sec)

5、二进制和字符类型之间的转换:

二进制类型(如BINARY、VARBINARY)和字符类型(如CHAR、VARCHAR)在某些上下文中可能会进行转换。但是,这种转换通常涉及到编码和字符集的问题,因此需要格外小心。

6、隐式转换的问题:

虽然隐式转换在某些情况下很方便,但它们也可能导致不可预测的结果和错误。为了避免这些问题,最好明确知道哪些类型的转换正在发生,并在必要时使用显式的类型转换函数(如 CAST() 或 CONVERT())。
隐式转换还可能导致性能问题,因为数据库需要花费额外的资源来执行这些转换。

7、查看隐式转换:

要查看MySQL是否对某个表达式进行了隐式转换,可以使用 EXPLAIN 语句(尽管这主要用于查看查询的执行计划,而不是直接的隐式转换)。但是,更好的方法是仔细检查SQL语句中的数据类型和操作符,并了解MySQL的隐式转换规则。

最后,要注意,虽然这里讨论了MySQL的隐式转换,但其他数据库系统也可能有类似的机制和行为。因此,在编写跨数据库的SQL代码时,需要格外小心数据类型和转换的问题。

出现这种因隐式转换产生的错误,是完全可以避免的低级错误
第一个是约束开发人员绝对不允许隐式转换发生
第二个是使用当下一些审核工具,产生隐式转换的语句应该审计提早避免上线生产环境。

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

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

相关文章

助力全息通信技术!GPS-Gaussian实现2K实时人体新视点合成

论文标题: GPS-Gaussian: Generalizable Pixel-wise 3D Gaussian Splatting for Real-time Human Novel View Synthesis 论文作者: Shunyuan Zheng, Boyao Zhou, Ruizhi Shao, Boning Liu, Shengping Zhang, Liqiang Nie, Yebin Liu 项目地址&#x…

vscode不能进行go跳转

辗转反侧,弄了好久好久终于出山了 总结:跟vscode版本插件有关 老版本vscode DocsTool修改成godoc 新版本vscode go get golang.org/x/tools/goplslatest setting中 "go.useLanguageServer": true, "[go]": {"editor.snipp…

7.无代码爬虫八爪鱼采集器软件——采集规则/项目的创建与网址输入

接上篇 6.零代码网页爬虫软件基础实操——下载与安装八爪鱼采集器 八爪鱼免费爬虫软件下载: 八爪鱼采集器下载 小白数据采集神器​​https://affiliate.bazhuayu.com/retrieve 直接复制粘贴要采集的网站在这里就可以进入采集规则的设计器 自定义任务 通过这个功能…

移动端浏览器调试工具vconsole

方案一&#xff1a;通过CDN地址引入 步骤一&#xff1a;通过CDN地址引入 <script src"https://cdn.bootcss.com/vConsole/3.2.2/vconsole.min.js"></script> 步骤二&#xff1a;实例化 <script> var vConsole new VConsole(); </script&g…

WebSocket——学习

WebSocket WebSocket 的基本概念什么是 WebSocket&#xff1f;WebSocket 的优点 WebSocket 的工作原理握手过程数据传输 WebSocket APIJavaScript WebSocket API WebSocket 服务器端实现使用 Java 实现 WebSocket 服务器使用 Netty 实现 WebSocket 服务器 WebSocket 应用场景总…

力学中应变的度量01——我好几年的疑惑终于有解了

文章目录 0、背景描述1、拉伸比&#xff08;率&#xff09; λ \lambda λ2、应变的引入3、一维应变概念的拓展4 总结 0、背景描述 在学校里的时候&#xff0c;我就一直很好奇应变的定义为何如此花里胡哨、五花八门&#xff0c;各种教材又都只是定义&#xff0c;从来不解释究竟…

Kylin V10 Server 下TongRDS独立哨兵服务配置手册

一、网络架构设计 部署类型 目录 IP Port 中心节点 /opt/rds/pcenter 10.8.3.34 6300 服务节点 /opt/rds/pmemedb 10.8.3.35 TongRDS 协议端口:6200 Redis 仿真端口:6379 哨兵监听端口:26379 10.8.3.36 二、部署服务节点 1.查看操作系统信息 [root@localhost ~]# cat /etc/.…

代码随想录算法训练营Day41|背包问题、分割等和子集

背包问题 二维 46. 携带研究材料&#xff08;第六期模拟笔试&#xff09; (kamacoder.com) dp数组有两维&#xff0c;横轴表示背包重量j&#xff08;0-j&#xff09;&#xff0c;纵轴表示不同物品&#xff08;0-i&#xff09;&#xff0c;dp[i][j]即表示从下标为[0-i]的物品…

使用volta管理前端开发环境

背景&#xff1a;公司有新老不同的产品&#xff0c;使用的node版本不一样&#xff0c;每次都要手动切换node版本&#xff0c;对应的项目才能运行。这样很麻烦&#xff0c;有没有好的解决方法&#xff0c;就找到了volta。 1.为什么是volta&#xff1f; 管网介绍&#xff1a;使用…

国内外典型的知识图谱项目

文章目录 早期的知识库项目互联网时代的知识图谱中文开放知识图谱垂直领域知识图谱 从人工智能的概念被提出开始&#xff0c;构建大规模的知识库一直都是人工智能、自然语言理解等领域的核心任务之一。下面分别介绍早期的知识库项目、互联网时代的知识图谱、中文开放知识图谱和…

MYSQL 字母大小转换

1、UCASE() 解释&#xff1a;把数值列(字段)的字每母转换为大写。 语法格式&#xff1a;SELECT UCASE(column_name) FROM table_name 中文注释&#xff1a;select UCASE(数值列/字段) from 表名 ; 用法&#xff1a; SELECT UCASE(column_name) FROM table_name;2、LCASE(…

【论文阅读笔记】PA-SAM: Prompt Adapter SAM for High-Quality Image Segmentation

1.论文介绍 PA-SAM: Prompt Adapter SAM for High-Quality Image Segmentation PA-SAM&#xff1a;用于高质量图像分割的提示适配器SAM 2024年 ICME Paper Code 2.摘要 Segment Anything Model&#xff0c;SAM在各种图像分割任务中表现出了优异的性能。尽管SAM接受了超过10亿…

# Mac环境如何安装Flutter:全面指南

Mac环境如何安装Flutter&#xff1a;全面指南 Flutter 是 Google 开发的开源移动 UI 框架&#xff0c;允许开发者使用 Dart 语言快速在 iOS 和 Android 上构建高质量的原生界面。本指南将详细指导您如何在 Mac 环境下安装 Flutter&#xff0c;确保您能够顺利开始 Flutter 开发…

软考又考了,数据库范式这次一定要弄懂!

0. 引言 今年数据库范式又作为选择题在软考中出题了&#xff0c;范式和反范式同样也在我们日常开发的数据库表设计工作中提供重要理论&#xff0c;今天我们来彻底弄懂几大范式的概念和区别&#xff0c;以及常见的反范式设计方法 1. 定义 1.1 基础概念 在实际讲解之前&#…

Python实现连连看12

4.2.5 获取图片连接方式 通过自定义函数getLinkType()获取图片的连接方式,代码如下所示。 def getLinkType(pre_row, pre_col, cur_row, cur_col):if pics_map[pre_row][pre_col] != pics_map[cur_row][cur_col]:return NONE_LINKif isNoCornerLink(pre_row, pre_col, cur_r…

嵌入式数据库_3.嵌入式数据库的主要功能及典型产品

1.嵌入式数据库的功能 嵌入式数据库的功能应与通用数据库功能相似&#xff0c;应覆盖数据库的核心功能。通常&#xff0c;嵌入式数据库有其自身的特殊需要&#xff0c;它应具备的功能包括以下4点&#xff1a; 足够高效的数据存储机制&#xff1b;数据安全控制&#xff08;锁机…

终于用上了桌面版本的chatGPT

最近经过不断的探索&#xff0c;也算是用上了桌面版本的chatgGPT&#xff0c;想要用同学&#xff0c;可以关注一下&#xff0c;后面我会出一期教程的&#xff5e;

docker安装elasticsearch8和kibana,带ik分词器

全文目录,一步到位 1.前言简介1.1 专栏传送门 2. elasticsearch和kibana安装2.1 准备工作2.1.1 下载elasticsearch2.1.2 下载kibana镜像 2.2 创建并运行es容器2.2.1 创建es网络2.2.2 创建es容器2.2.3 放行端口2.2.4 访问查看结果> 步骤一: 点击高级, 然后继续访问> 步骤二…

力扣878.第N个神奇数字

力扣878.第N个神奇数字 二分答案 check()&#xff1a;公共部分为最大公倍数的倍数 class Solution {const long MOD 1e9 7;public:int nthMagicalNumber(int n, int a, int b) {//lcm函数 求最大公倍数long lcm std::lcm(a,b);auto check [&](long long mid) -> …

KIVY AliasProperty 运用报错汇总

案例1&#xff1a; 在Kivy中&#xff0c;AliasProperty 允许你创建一个属性的别名&#xff0c;该别名可以基于其他属性计算得到。但是&#xff0c;与普通的Python属性不同&#xff0c;Kivy的Property类&#xff08;包括AliasProperty&#xff09;并没有直接提供定义getter和s…