当前位置: 首页 > 后端技术 > Java

记得过滤失败的问题是id关联查询导致的,其实是varchar和bigint之间的转换问题

时间:2023-04-01 23:46:12 Java

今天在test库上做关联查询的时候,出现了取冗余值的情况。现在更改表名并再次复制它。解释。如图,现有两张user表,role表关联rid和role表的id。从图中的数据中只能看到id和alias字段。理论上执行下面的sql应该会出现下图结果,一个用户对应一个角色,有1条数据SELECT*fromrd_useru,rd_rolerwhereu.rid=r.idwherer。id=123456789012345611但是实际上上面语句执行的时候出现了2条数据,如图一开始我一头雾水。怀疑是我对join的理解有问题。各种join后百度确定我的理解是正确的。然后我试了几次一步一步的查询,还是得到了错误的结果。最后在重新检查表结构的时候,发现了一个非常坑爹的地方。user表的rid数据类型其实是varchar,但是role的id字段是bigint。下面是没有问题的,但是经过反复尝试,发现当这个字段的长度大于16位时(这个结论不是很准确),就会出现上图。这样就解决了将user表的rid字段改成bigint后查询出错的问题。按理说事情就这样结束了,可是我还是不能释怀,为什么数据库会出问题呢?于是查了一会儿资料,有了一些小发现。在一篇文章中,一位博主遇到了另一种情况:他的问题是char和int,当他执行select0='abc'时,发现结果为真。根据他的博文,他在mysql官方文档中写道,有数字和字符串在进行比较时会自动转换。其中,varchar如果是数字和字母的组合,会自动截取前面的数字,和数字进行比较。例如,下面这句话的结果也是成立的。select1='1abc'官方文档地址MySQL::MySQL5.7参考手册::12.4.2ComparisonFunctionsandOperators比较运算的结果为1(TRUE)、0(FALSE)或NULL。这些操作适用于数字和字符串。根据需要,字符串会自动转换为数字,数字也会自动转换为字符串。比较运算的结果是1(TRUE)、0(FALSE)或NULL。这些操作适用于数字和字符串。必要时字符串自动转换为数字,数字自动转换为字符串。光看这句话,官网说的比较笼统。没有说怎么转换,也解决不了我的问题。几轮百度关键词修改后,没有出现想要的结果。我在Bing上搜索并找到了一些东西。其实那个答案也是来自官网的说明书。MySQL::MySQL8.0参考手册::12.3表达式求值中的类型转换本节讲述在执行比较操作时如何转换数据。在所有其他情况下,参数将作为浮点(双精度)数字进行比较。例如,字符串和数字操作数的比较是作为浮点数的比较进行的。在所有其他情况下,参数将作为浮点(双精度)数字进行比较。例如,字符串和数字操作数的比较作为浮点数的比较来执行。也就是说,varchar和bigint比较的时候,其实是先转成double再比较。即使你不知道双精度损失的原理,你也一定听说过。既然查到这里了,我也想知道这个值大了会损失精度。有兴趣的同学可以自行查看浮点精度的损失,关键部分贴在这里。在计算机中,浮点数由IEEE754标准定义。什么是IEEE754?维基百科是这样解释的:IEEE754规定了四种表示浮点值的方式:单精度(32位)、双精度(64位)、扩展单精度(超过43位,很少使用)和扩展双精度(79+位,通常以80位实现)。这就是我关心的。浮点数是8个字节和64位。位数如图所示。实际位数只有52。这里有一个可以计算浮点数的在线网站IEEE754计算器(weitz.de)例如整数5。转换为二进制是101(滚动和除法)。计算机会将其转换成第一位为1,然后是小数点,然后是尾数的形式,如下图所示。这里要注意,标准中强制要求第一位为1,而52位的尾数占了53个槽位,因此该值为2^53之后的数据可能不安全。我们来做个实验,2的53次方-1的值为9007199254740991,2的53次方为9007199254740992,2的53次方+1为9007199254740993看下图,从9007199254740992开始,转换后的位数intobinary是54位,因为浮点数最多只能存53位,所以舍弃最后一位9007199254740992==9007199254740993建立的浏览器的控制台这里也可以直接输出结果,终于知道原因了查询问题。即整数转换成二进制后,如果大于53位,只要前53位的值相同,它们之间的=号就可以返回true。(上面有错误,Long模拟不了,需要看实际的double值)这次查资料得出结论,官网文档确实很重要。但是因为我们的母语不是英语,所以我们很少把文档当作书来读,只有出了问题才会想起。即使我们偶尔使用翻译工具进行参考,翻译出来的东西也不会在阅读后在脑海中留下印象。我们在这方面确实处于劣势。