对于小数的表示,mysql分为浮点型和定点型两种。浮点行为FLOAT和DOUBLE,定点型只有DECIMAL。定点型在数据库中以字符串的形式存放,因此更为精确,一般表示货币等比较精确的数据。
他们都可以使用类型名称后加(M,D)来表示,M表示一共显式几位数字,D表示表示小数位数,M和D又称为精度和标度。当DECIMAL没有精度和标度是默认为DECIMAL(10,0)。我们创建表tDec,并且分别将字段id1,id2,id3字段设置为FLOAT(5,2),DOUBLE(5,2),DECIMAL(5,2),分别插入值都为为1.34。
mysql> create table tDec(
-> id1 FLOAT(5,2),
-> id2 DOUBLE(5,2),
-> id3 DECIMAL(5,2)
-> );
Query OK, 0 rows affected (0.20 sec)
mysql> insert into tDec values(1.34,1.34,1.34);
Query OK, 1 row affected (0.49 sec)
mysql> select * from tDec;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.34 | 1.34 | 1.34 |
+------+------+------+
1 row in set (0.00 sec)
我们可以发现数据正确的插入了数据表中。我们再次插入数据,观察插入后的结果:
mysql> insert into tDec values(1.344,1.344,1.344);
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> insert into tDec values(1.345,1.345,1.345);
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> insert into tDec values(1.3451,1.3451,1.3451);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> insert into tDec values(1.3411,1.3451,1.3461);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> insert into tDec values(1.3451,1.3450,1.3451);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from tDec;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.34 | 1.34 | 1.34 |
| 1.34 | 1.34 | 1.34 |
| 1.34 | 1.34 | 1.35 |
| 1.35 | 1.35 | 1.35 |
| 1.34 | 1.35 | 1.35 |
| 1.35 | 1.34 | 1.35 |
+------+------+------+
6 rows in set (0.00 sec)
通过上面的结果我们可以看到,当一个字段被定义为浮点型后,如果插入的精度超多该列定义的实际精度,则插入值会被四舍五入到实际定义的精度,然后插入,插入过程中不会报错。定点数在四舍五入插入的过程中会给予警告,如果是在传统模式下会报错,无法插入数据。浮点型在四舍五入的时候还会看决定是舍还是入的那一位的下一位是否存在不存在(是否非0)则直接截断,存在才会四舍五入。我们通过第三条和第四条和第六条数据作比较可以得到这个结论。
同时我们不声明精度和标度,建立表tDec1,并且插入数据,显示结果为:
mysql> create table tDec1(
-> id1 FLOAT,
-> id2 DOUBLE,
-> id3 DECIMAL
-> );
Query OK, 0 rows affected (0.02 sec)
mysql> insert into tDec1 values(1.3,1.3,1.3);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> insert into tDec1 values(1.5,1.5,1.5);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> insert into tDec1 values(1.1,1.5,1.6);
Query OK, 1 row affected, 1 warning (0.00 sec)
mysql> select * from tDec1;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.3 | 1.3 | 1 |
| 1.5 | 1.5 | 2 |
| 1.1 | 1.5 | 2 |
+------+------+------+
3 rows in set (0.00 sec)
当都不生声明M和D时,FLOAT和DOUBLE会按实际值插入,DECIMAL默认为DECIMAL(10,0),按四舍五入方式插入。
下面我们再看一个关于浮点数和定点数的精确度问题。
mysql> create table tDec2(
-> id1 FLOAT(10,2),
-> id2 DECIMAL(10,2)
-> );
Query OK, 0 rows affected (0.07 sec)
mysql> insert into tDec2 values(131072.32,131072.32);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tDec2;
+-----------+-----------+
| id1 | id2 |
+-----------+-----------+
| 131072.31 | 131072.32 |
+-----------+-----------+
1 row in set (0.00 sec)
从上面的例子可以看出再插入的时候浮点型的数产生了误差,这个是浮点数特有的问题。因为对于精度要求比较高的应该使用DECIMAL定点数类型,而不是浮点数类型。
来源:oschina
链接:https://my.oschina.net/u/2665064/blog/786963