【发布时间】:2011-10-13 11:00:15
【问题描述】:
好的,所以我知道有很多文章说我不应该使用 DOUBLE 在 MySQL 数据库上存储资金,否则我最终会遇到棘手的精度错误。关键是我不是在设计一个新的数据库,而是要求我找到优化现有系统的方法。较新的版本包含 783 个 DOUBLE 类型的列,其中大部分用于存储货币或用于计算货币金额的公式。
所以我对这个主题的第一个意见是,我强烈建议在下一个版本中将 DOUBLE 转换为 DECIMAL,因为 MySQL 文档和每个人都这么说。但后来我找不到任何好的论据来证明这一建议的合理性,原因有以下三个:
- 我们不对数据库执行任何计算。所有操作都在 Java 中使用 BigDecimal 完成,而 MySQL 仅用作结果的普通存储。
- DOUBLE 提供的 15 位精度已经足够了,因为我们主要存储 2 位小数的金额,偶尔也会存储带有 8 位小数的公式参数。
- 我们有 6 年的生产记录,没有由于 MySQL 端的精度损失而导致的已知错误问题。
即使对 18 百万行的表执行操作,例如 SUM 和复数乘法,我也无法执行精度不足的错误。我们实际上并没有在生产中做这种事情。我可以通过执行类似
的操作来显示丢失的精度SELECT columnName * 1.000000000000000 FROM tableName;
但我想不出办法将它变成小数点后第二位的错误。我在互联网上发现的大多数实际问题都是 2005 年和更早的论坛条目,我无法在 5.0.51 MySQL 服务器上重现它们。
因此,只要我们不执行任何我们不打算执行的 SQL 算术运算,我们是否应该预期仅在 DOUBLE 列中存储和检索金额会出现任何问题?
【问题讨论】:
-
您是否在Java中计算应税金额,然后在存储之前根据合同对其进行四舍五入?例如,如果您销售 1.47 美元的商品并缴纳 8.25% 的当地销售税,则您可能需要记录 0.121275 美元的税款。我想知道您在数据库中存储这种字段的形式是什么,以及您是否在存储之前四舍五入到 0.12 美元(或四舍五入到 0.13 美元,具体取决于您的语言环境)。
-
是的,我们在 Java 中计算税款,我们存储商品的价格、四舍五入到小数点后第 4 位的税额和四舍五入到小数点后第 2 位的总价格。因此,在您的示例中,一行将包含 1.47、0.1213 和 1.59。 8.25% 以 0.08250000 的形式存储在其他地方,并且不会在每次销售中重复。