use*_*961 63 mysql double decimal
好的,所以我知道有很多文章说我不应该使用DOUBLE来存储MySQL数据库,否则我最终会遇到棘手的精确错误.关键是我没有设计新的数据库,我要求找到优化现有系统的方法.较新的版本包含783个DOUBLE类型列,其中大多数用于存储金钱或公式来计算金额.
所以我对这个主题的第一个看法是我应该强烈推荐在下一个版本中从DOUBLE到DECIMAL的转换,因为MySQL doc和每个人都这么说.但是后来我找不到任何好的论据来证明这个推荐是正确的,原因有三:
即使通过在18毫米行表上执行操作,如SUM和复数乘法,我也无法执行精度不足的错误.而且我们实际上并没有在生产中做这类事情.我可以通过做类似的事情来显示精确度
SELECT columnName * 1.000000000000000 FROM tableName;
但我想不出办法把它变成第二个十进制数的错误.我在互联网上发现的大多数实际问题都是2005年和更早的论坛条目,我无法在5.0.51 MySQL服务器上重现它们.
因此,只要我们不执行任何我们不打算执行的SQL算术运算,我们应该期望只在DOUBLE列中存储和检索金额吗?
bas*_*sh- 46
实际上它是完全不同的.DOUBLE导致舍入问题.如果你做类似的0.1 + 0.2事情会给你类似的东西0.30000000000000004.我个人不相信使用浮点数学的财务数据.影响可能很小,但谁知道.我宁愿让我所知道的是可靠的数据,而不是近似的数据,特别是当你处理货币价值时.
bro*_*and 34
来自MySQL文档的示例http://dev.mysql.com/doc/refman/5.1/en/problems-with-float.html(我收缩它,本节的文档与5.5相同)
mysql> create table t1 (i int, d1 double, d2 double);
mysql> insert into t1 values (2, 0.00 , 0.00),
(2, -13.20, 0.00),
(2, 59.60 , 46.40),
(2, 30.40 , 30.40);
mysql> select
i,
sum(d1) as a,
sum(d2) as b
from
t1
group by
i
having a <> b; -- a != b
+------+-------------------+------+
| i | a | b |
+------+-------------------+------+
| 2 | 76.80000000000001 | 76.8 |
+------+-------------------+------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
基本上如果你得到一个你得到0-13.2 + 59.6 + 30.4 = 76.8.如果我们总结b,我们得到0 + 0 + 46.4 + 30.4 = 76.8.a和b的总和是相同的,但MySQL文档说:
在SQL语句中写入的浮点值可能与内部表示的值不同.
如果我们用十进制重复相同的话:
mysql> create table t2 (i int, d1 decimal(60,30), d2 decimal(60,30));
Query OK, 0 rows affected (0.09 sec)
mysql> insert into t2 values (2, 0.00 , 0.00),
(2, -13.20, 0.00),
(2, 59.60 , 46.40),
(2, 30.40 , 30.40);
Query OK, 4 rows affected (0.07 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select
i,
sum(d1) as a,
sum(d2) as b
from
t2
group by
i
having a <> b;
Empty set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
预期的结果是空集.
因此,只要您不执行任何SQL arithemetic操作,您就可以使用DOUBLE,但我仍然更喜欢DECIMAL.
关于DECIMAL的另一个注意事项是如果小数部分太大则会四舍五入.例:
mysql> create table t3 (d decimal(5,2));
Query OK, 0 rows affected (0.07 sec)
mysql> insert into t3 (d) values(34.432);
Query OK, 1 row affected, 1 warning (0.10 sec)
mysql> show warnings;
+-------+------+----------------------------------------+
| Level | Code | Message |
+-------+------+----------------------------------------+
| Note | 1265 | Data truncated for column 'd' at row 1 |
+-------+------+----------------------------------------+
1 row in set (0.00 sec)
mysql> select * from t3;
+-------+
| d |
+-------+
| 34.43 |
+-------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
小智 16
我们刚刚经历过同样的问题,但反过来说.也就是说,我们将美元金额存储为DECIMAL,但现在我们发现,例如,MySQL正在计算值4.389999999993,但是当将其存储到DECIMAL字段时,它将其存储为4.38而不是4.39,就像我们想要的那样它来.因此,虽然DOUBLE可能会导致舍入问题,但似乎DECIMAL也会导致一些截断问题.