mysql 并发插入浮点数据异常_5分钟搞懂MySQL数据类型之浮点型FLOAT类型

5分钟搞懂MySQL数据类型

之浮点型--FLOAT类型

MySQL支持的浮点类型有两个:FLOAT和DOULE。单精度的FLOAT占用4个字节的空间,双精度的DOUBLE占用8个字节的空间。

对于FLOAT,MySQL支持非标准语法,如:FLOAT(M,D)、REAL(M,D)或DOUBLE PRECISION(M,D)。这里(M,D)分别是数值位数和小数点后的位数。例如FLOAT(7,4)的最大值即是999.9999。MySQL会对保存的数值进行四舍五入,例如插入999.00009到类型定义为FLOAT(7,4)的列时,保存的近似值是999.0001。

mysql> create table t1(v float(7,4));

Query OK, 0 rows affected, 1 warning (0.13 sec)

mysql> insert into t1 values (999.00009);

Query OK, 1 row affected (0.02 sec)

mysql> select * from t1;

+----------+

| v        |

+----------+

| 999.0001 |

+----------+

1 row in set (0.01 sec)

浮点数中保存的是近似值而非精确值,如果把它当成精确值处理,可能会造成一定的困扰。SQL语句里的浮点数可能会跟内部展现的不同,这个示例还是很能说明问题:

mysql> CREATE TABLE t1 (i INT, d1 DOUBLE, d2 DOUBLE);

Query OK, 0 rows affected (0.05 sec)

mysql> INSERT INTO t1 VALUES (1, 101.40, 21.40), (1, -80.00, 0.00),

    -> (2, 0.00, 0.00), (2, -13.20, 0.00), (2, 59.60, 46.40),

    -> (2, 30.40, 30.40), (3, 37.00, 7.40), (3, -29.60, 0.00),

    -> (4, 60.00, 15.40), (4, -10.60, 0.00), (4, -34.00, 0.00),

    -> (5, 33.00, 0.00), (5, -25.80, 0.00), (5, 0.00, 7.20),

    -> (6, 0.00, 0.00), (6, -51.40, 0.00);

Query OK, 16 rows affected (0.01 sec)

Records: 16  Duplicates: 0  Warnings: 0

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING a <> b;

+------+-------+------+

| i    | a     | b    |

+------+-------+------+

|    1 |  21.4 | 21.4 |

|    2 |  76.8 | 76.8 |

|    3 |   7.4 |  7.4 |

|    4 |  15.4 | 15.4 |

|    5 |   7.2 |  7.2 |

|    6 | -51.4 |    0 |

+------+-------+------+

6 rows in set (0.00 sec)

前5条记录a/b的值肉眼看起来完全相同,但为什么没能被having条件过滤掉呢,因为a/b两列只是看起来没有区别,而实际上确实不同,只不过数值的差异是在小数点10位以后,具体保存的数值基于计算机体系架构或编译版本和优化级别,比如说不同CPU类型计算的浮点型数值可能不同。

正确的执行浮点数值比较的方式,首先确定一个可接受的数值比较的精度值,比如说我们能够接受浮点数的精度在千分之一内就认为相同,那么我们可以将比较语句做些修改:

mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1 GROUP BY i HAVING ABS(a - b) > 0.0001;

+------+-------+------+

| i    | a     | b    |

+------+-------+------+

|    6 | -51.4 |    0 |

+------+-------+------+

1 row in set (0.00 sec)

如果D1/D2两列是DECIMAL数值类型,那么上述SELECT语句应该只返回一条记录。所以,如果确实对数值的存储精度没有要求,可以考虑使用FLOAT类型,否则还是使用精确数值的数据类型较好。

另外,从MySQL8.0.17版本开始,非标的FLOAT(M,D)和DOUBLE(M,D)语法即已被废弃,并且FLOAT和DOUBLE类型的列不再支持AUTO_INCREMENT属性,使用时也要注意。

75bec1b907ccc2e296f6ca37890b95cc.gif

点击了解:5分钟搞懂MySQL数据类型之整型--INT类型

              5分钟搞懂MySQL数据类型之数值型--DECIMAL类型

f837b3873a51fb313fa66c6ec490ba48.gifEND 1c691fd12292b1830f24e524637849ae.png扫码关注我们勤勤恳恳,善始善终持之以恒,专心致志 f837b3873a51fb313fa66c6ec490ba48.gif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值