欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Mysql 查询float类型的字段查询不到结果

程序员文章站 2022-07-15 13:18:20
...

问题:

select * from payments where status = 1 and payment_fee = 0.31

查询结果为空(可四数据库明明有一条数据满足条件的)

解决:

  • 使用format
select * from payments where status = 1 and  format(payment_fee,2) = format(0.31,2);
  • 使用concat
select * from payments where status = 1 and  concat(payment_fee, '') = '0.31'
  • 使用like
select * from payments where status = 1 and payment_fee like 0.31

原因深究:

大意:FLOAT和DOUBLE类型表示近似数字数据值。 MySQL对单精度值使用四个字节,对双精度值使用八个字节。

对于FLOAT,SQL标准允许在括号中的关键字FLOAT后面的位中指定精度(而不是指数的范围)的可选规范。 ;即FLOAT(p)。 MySQL还支持此可选的精度规范,但是FLOAT(p)中的精度值仅用于确定存储大小。从0到23的精度导致4字节单精度FLOAT列。从24到53的精度将导致8字节的双精度DOUBLE列。

MySQL允许使用非标准语法:FLOAT(M,D)或REAL(M,D)或DOUBLE PRECISION(M,D)。在此,(M,D)表示总共可以存储多达M位的值,其中D位可以在小数点后。例如,显示为FLOAT(7,4)的列看起来像-999.9999。 MySQL在存储值时执行四舍五入,因此,如果将999.00009插入FLOAT(7,4)列,则近似结果为999.0001。

由于浮点值是近似值而不是作为精确值存储的,因此在比较中尝试将它们视为精确值可能会导致问题。它们还受平台或实现依赖性的约束。有关更多信息,请参见第B.4.4.8节“浮点值的问题”

为了获得最大的可移植性,需要存储近似数值数据值的代码应使用FLOAT或DOUBLE PRECISION,而没有规定精度或位数。

以上大意: 使用基于语句的复制,值从十进制转换为二进制。由于十进制和二进制表示形式之间的转换可能是近似的,因此涉及浮点值的比较是不精确的。对于显式使用浮点值或隐式转换为浮点值的操作,这是正确的。由于计算机架构,用于构建MySQL的编译器等方面的差异,浮点值的比较可能在主服务器和从属服务器上产生不同的结果。

ps:
float类型不指定精度时,对float列的精确检索可能不正确。
使用float还会存在一个问题是insert时会存在数据丢失问题。
例如我insert一个字段为 131072.32 的值到数据库,成功之后实际到数据库的是 131072.31。。。少了0.01.。。。所以float大家还是要慎用

关于MySQL如何选择float, double, decimal可以参考这篇文章,通俗易懂:
http://blog.leanote.com/post/weibo-007/mysql_float_double_decimal