SET sql_mode = “REAL_AS_FLOAT”;
问题1: FLOAT 和 DOUBLE 这两种数据类型的区别是什么?
FLOAT 占用字节数少,取值范围小;DOUBLE 占用字节数多,取值范围也大。
问题2: 为什么浮点数类型的无符号数取值范围,只相当于有符号数取值范围的一半,也就是只相当于有符号数取值范围大于等于零的部分呢?
MySQL 存储浮点数的格式为:符号(S)、尾数(M)和 阶码(E)。因此,无论有没有符号,MySQL 的浮点数都会存储表示符号的部分。因此, 所谓的无符号数取值范围,其实就是有符号数取值范围大于等于零的部分。
对于浮点类型,在MySQL中单精度值使用4个字节,双精度值使用8个字节。
MySQL允许使用非标准语法(其他数据库未必支持,因此如果涉及到数据迁移,则最好不要这么用):FLOAT(M,D)或DOUBLE(M,D)。这里,M称为精度,D称为标度。(M,D)中 M=整数位+小数位,D=小数位。 D<=M<=255,0<=D<=30。
例如,定义为FLOAT(5,2)的一个列可以显示为-999.99-999.99。如果超过这个范围会报错。
FLOAT和DOUBLE类型在不指定(M,D)时,默认会按照实际的精度(由实际的硬件和操作系统决定)来显示。
说明:浮点类型,也可以加UNSIGNED,但是不会改变数据范围,例如:FLOAT(3,2) UNSIGNED仍然只能表示0-9.99的范围。
不管是否显式设置了精度(M,D),这里MySQL的处理方案如下:
从MySQL 8.0.17开始,FLOAT(M,D) 和DOUBLE(M,D)用法在官方文档中已经明确不推荐使用,将来可能被移除。另外,关于浮点型FLOAT和DOUBLE的UNSIGNED也不推荐使用了,将来也可能被移除。
举例
CREATE TABLE test_double1( f1 FLOAT, f2 FLOAT(5,2), f3 DOUBLE, f4 DOUBLE(5,2) ); DESC test_double1;
INSERT INTO test_double1(f1, f2) VALUES(123.45,123.45); SELECT * FROM test_double1;
INSERT INTO test_double1(f3,f4) VALUES(123.45,123.456); #存在四舍五入
INSERT INTO test_double1(f3,f4) VALUES(123.45,1234.456);
浮点数类型有个缺陷,就是不精准。下面我来重点解释一下为什么 MySQL 的浮点数不够精准。比如,我们设计一个表,有f1这个字段,插入值分别为0.47,0.44,0.19,我们期待的运行结果是:0.47 + 0.44 + 0.19 = 1.1。而使用sum之后查询:
CREATE TABLE test_double2( f1 DOUBLE ); INSERT INTO test_double2 VALUES(0.47),(0.44),(0.19);
mysql> SELECT SUM(f1) -> FROM test_double2; +--------------------+ | SUM(f1) | +--------------------+ | 1.0999999999999999 | +--------------------+ 1 row in set (0.00 sec)
mysql> SELECT SUM(f1) = 1.1,1.1 = 1.1 -> FROM test_double2; +---------------+-----------+ | SUM(f1) = 1.1 | 1.1 = 1.1 | +---------------+-----------+ | 0 | 1 | +---------------+-----------+ 1 row in set (0.00 sec)
上一篇:SQL的七种JOIN