MySQL数字太长隐式转换

4 篇文章 0 订阅

开开心心写程序,程序出错,出错又出错。。。。。。。。。。卒

 

进入正题☞MySQL数字对比char类型,隐性转换

select * from t_pr_apply where APPLY_ID =532922233950044176;

这样的数据库语句,apply_id是varchar(32) 而后面很明显是数字

这样查出的结果是。。。。

 

一堆值,实际上,我只要一个值,结果是这么多,查了百度后发现,大概是这样的

where条件的类型自动转换,就是对于的类型不会装换,不对应的类型就会转换,

按照这样的说法,当where条件之后的值的类型和表结构不一致的时候,MySQL会做隐式的类型转换,所以我觉得我上面的那个18位的id是被转换了,而且有可能发生了数据截取,就是变成了 like ‘5329222339500441%’这样来查询,所以查询了这么多的数据。

但是经过测试数据,发现并不是上面我所说的那样子

但是确实好像是发生了隐性转换,并全表查询,产生了慢查询

为了解决这个困惑,我查询了官方文档

当运算符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。某些转换是隐式发生的。例如,MySQL会根据需要自动将字符串转换为数字,反之亦然。

SELECT 1+'1';
        -> 2
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'

有关隐式数字到字符串转换的字符集以及适用于CREATE TABLE ... SELECT 语句的已修改规则的信息,请参阅本节后面的内容。

以下规则描述了比较操作的转换方式:

  • 如果一个或两个参数都是NULL,则比较的结果是NULL,除了NULL-safe <=> 相等比较运算符。因为NULL <=> NULL,结果是真的。无需转换。

  • 如果比较操作中的两个参数都是字符串,则将它们作为字符串进行比较。

  • 如果两个参数都是整数,则将它们作为整数进行比较。

  • 如果不与数字进行比较,十六进制值将被视为二进制字符串。

  • 如果其中一个参数是a TIMESTAMP或 DATETIME列而另一个参数是常量,则在执行比较之前将常量转换为时间戳。这样做是为了更友好的ODBC。这不是针对参数的 IN()。为安全起见,在进行比较时始终使用完整的日期时间,日期或时间字符串。例如,要在使用BETWEEN日期或时间值时获得最佳结果 ,请使用CAST()显式将值转换为所需的数据类型。

  • 如果其中一个参数是十进制值,则比较取决于另一个参数。如果另一个参数是十进制或整数值,则将参数作为十进制值进行比较,如果另一个参数是浮点值,则将参数作为浮点值进行比较。

  • 在所有其他情况下,参数被比较为浮点(实数)。

有关将值从一种时间类型转换为另一种时间类型的信息,请参见第11.3.7节“日期和时间类型之间的转换”

以下示例说明了将字符串转换为数字以进行比较操作:

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

为了比较字符串列和数字,MySQL不能使用列上的索引来快速查找值。如果 str_col是索引字符串列,则在以下语句中执行查找时,不能使用索引:

SELECT * FROM tbl_name WHERE str_col=1;

这样做的原因是,有许多不同的字符串可以转换为价值1,例如 '1'' 1'或 '1a'

使用浮点数(或转换为浮点数的值)的比较是近似的,因为这些数字是不精确的。这可能会导致结果看起来不一致:

mysql> SELECT '18015376320243458' = 18015376320243458;
        -> 1
mysql> SELECT '18015376320243459' = 18015376320243459;
        -> 0

这样的结果可能会发生,因为值被转换为浮点数,它只有53位的精度并且可以舍入:

mysql> SELECT '18015376320243459'+0.0;
        -> 1.8015376320243e+16

此外,从字符串到浮点以及从整数到浮点的转换不一定以相同的方式发生。整数可以由CPU转换为浮点数,而字符串在涉及浮点乘法的运算中逐位转换。

显示的结果将因系统而异,并且可能受计算机体系结构或编译器版本或优化级别等因素的影响。避免此类问题的一种方法是使用CAST()以便不将值隐式转换为浮点数:

mysql> SELECT CAST('18015376320243459' AS UNSIGNED) = 18015376320243459; -> 1

 

到这里终于明白,为什么会查出这么多条数据了,原来都是精度惹的祸

SELECT '532922233950044176'+0.0;
SELECT '532922233950044175'+0.0
SELECT '532922233950044164'+0.0;
SELECT '532922233950044175'= 532922233950044176;
SELECT '532922233950044100'= 532922233950044176;

以上还是有些问题,就比如为什么'532922233950044100'= 532922233950044176;就不相等呢

至今对我来说仍是个迷。。。。。。。。☹

 

算了,还是直接解决问题吧,上面官方文档有介绍,虽然我这里是跟上面不太一样,但是原理是一样的

因为我传的是一段很长的数据,所以需要在java先进行的截取

我使用的是一个StringUtils 的工具类,里面含有split 的方法,将字符串用逗号分隔开来

先进行截图,存为数组,我这里存到数据库是用map,所以在数据库也要搞一搞

 

item对应的applyid 需要跟下面的#{applyid}的#{}里面的值对应。

foreach属性

属性

描述

item

循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。

具体说明:在list和数组中是其中的对象,在map中是value。

该参数为必选。

collection

要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象用map代替作为键。

当然在作为入参时可以使用@Param("keyName")来设置键,设置keyName后,list,array,map将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:

如果User有属性List ids。入参是User对象,那么这个collection = "ids"

如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"

上面只是举例,具体collection等于什么,就看你想对那个元素做循环。

该参数为必选。

separator

元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。

open

foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。

close

foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。

index

在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值