摘要:
公司项目数据库中存储金额字段使用float类型,在金额达到10W时出现小数丢失,部分数据四舍五入的问题,将数据类型替换为DECIMAL后解决该问题。主要原因就是原来人员没有搞清楚float的使用陷阱和使用场景,以下内容就是自己查找部分同学的资料后实验所得。
MySQL官方文档
FLOAT[(M[, D])]数据类型是单精度浮点数, 默认大小为24位数字,精度大约7位数字(经测试为6位),当设置M大小大于24时,自动转换为DOUBLE类型;
同时设置M和D时不进行自动转换。
测试实验1
mysql > create table float_test(id int, float_test float);
mysql > desc float_test;
+------------+---------+------+-----+---------+-------+
| Field| Type| Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| id| int(11) | YES|| NULL||
| float_test | float| YES|| NULL||
+------------+---------+------+-----+---------+-------+
mysql > insert into float_test values(1, 123456),(2, 123.456),(3, 1234567),(4,1234.5678);
mysql > select * from float_test;
+------+------------+
| id| float_test |
+------+------------+
|1 |123456 |
|2 |123.456 |
|3 |123570 |
|4 |1234.57 |
+------+------------+
从上面测试代码可知float默认保存6位精度(包括小数位和整数位),超过6位会被四舍五入并补入0.
测试实验2
mysql > alter table float_test add float_4 float(4);
mysql > desc float_test;
+------------+---------+------+-----+---------+-------+
| Field| Type| Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| id| int(11) | YES|| NULL||
| float_test | float| YES|| NULL||
| float_4| float| YES|| NULL||
+------------+---------+------+-----+---------+-------+
由数据表结构来看,float(m)是没有效果的,和float效果一致(根据文档m<24时相当于24).
测试实验3
mysql > alter table float_test add float_4_2 float(4,2);
mysql > desc float_test;
+------------+------------+------+-----+---------+-------+
| Field| Type| Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| id| int(11)| YES|| NULL||
| float_test | float| YES|| NULL||
| float_4| float| YES|| NULL||
| float_4_2| float(4,2) | YES|| NULL||
+------------+------------+------+-----+---------+-------+
mysql > insert into float_test(id,float_4_2) values(5, 12),(6, 12.4), (7, 12.34);
(填写其他整数部分位数大于2的均会报错,但使用ORM框架不会报错)
mysql > select * from float_test where id > 4;
+------+------------+---------+-----------+
| id| float_test | float_4 | float_4_2 |
+------+------------+---------+-----------+
|5 |NULL |NULL |12.00 |
|6 |NULL |NULL |12.40 |
|7 |NULL |NULL |12.34 |
+------+------------+---------+-----------+
mysql > update float_test set float_4_2=12.3456 where id = 5;
mysql> select * from float_test where id > 4
+------+------------+---------+-----------+
| id| float_test | float_4 | float_4_2 |
+------+------------+---------+-----------+
|5 |NULL |NULL |12.35 |
|6 |NULL |NULL |12.40 |
|7 |NULL |NULL |12.34 |
+------+------------+---------+-----------+
由上可知,设置m和d是有效果的,小数不够位补0; 当小数位多时进行四舍五入.
测试实验4
mysql> alter table float_test add float_25 float(25);
mysql> desc float_test;
+------------+------------+------+-----+---------+-------+
| Field| Type| Null | Key | Default | Extra |
+------------+------------+------+-----+---------+-------+
| id| int(11)| YES|| NULL||
| float_test | float| YES|| NULL||
| float_4| float| YES|| NULL||
| float_4_2| float(4,2) | YES|| NULL||
| float_25| double| YES|| NULL||
+------------+------------+------+-----+---------+-------+
当m大于24时,数据类型转换为double类型.
测试实验5
mysql> alter table float_test add float25_2 float(25,2);
mysql> desc float_test;
+------------+-------------+------+-----+---------+-------+
| Field| Type| Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| id| int(11)| YES|| NULL||
| float_test | float| YES|| NULL||
| float_4| float| YES|| NULL||
| float_4_2| float(4,2)| YES|| NULL||
| float_25| double| YES|| NULL||
| float25_2| float(25,2) | YES|| NULL||
+------------+-------------+------+-----+---------+-------+
mysql> insert into float_test(id, float25_2) values(8, 12345678901234567890123.12);
mysql> select * from float_test where id > 7;
+------+------------+---------+-----------+----------+----------------------------+
| id| float_test | float_4 | float_4_2 | float_25 | float25_2|
+------+------------+---------+-----------+----------+----------------------------+
|8 |NULL |NULL |NULL |NULL | 12345679377913908000000.00 |
+------+------------+---------+-----------+----------+----------------------------+
有由上可知,当m和d同时设置时,尽管m大于24,但是不会进行转换; 同时数值还会变得不准确,小数位被0填充。
【MySQL的float数据类型注意】注:
float的d最大限制不能超过30
推荐阅读
- mysql|InnoDB数据页结构
- javaweb|基于Servlet+jsp+mysql开发javaWeb学生成绩管理系统
- mysql|一文深入理解mysql
- Java毕业设计项目实战篇|Java项目:在线嘿嘿网盘系统设计和实现(java+Springboot+ssm+mysql+maven)
- SQL|SQL基本功(五)--函数、谓词、CASE表达式
- vue|电商后台管理系统(vue+python|node.js)
- Java及基础算法及数据结构|旧笔记整理(MySQL)
- mysql|双非本211硕,无实习无项目,自学大数据开发,秋招上岸
- 数据库|Mysql--InnoDB存储引擎详解
- MySQL学习笔记-9-order by