在mysql中存储金额

Posted

技术标签:

【中文标题】在mysql中存储金额【英文标题】:storing money amounts in mysql 【发布时间】:2011-01-16 02:46:27 【问题描述】:

我想将 3.50 存储到一个 mysql 表中。我有一个存储它的浮点数,但它存储为 3.5,而不是 3.50。我怎样才能让它有尾随零?

【问题讨论】:

【参考方案1】:

不要将货币值存储为浮点数,使用 DECIMAL 或 NUMERIC 类型:

Documentation for MySQL Numeric Types

编辑和澄清:

浮点值很容易受到舍入误差的影响,因为它们的精度有限,所以除非你不在乎你只得到 9.99 而不是 10.00,否则你应该使用 DECIMAL/NUMERIC,因为它们是不存在此类问题的定点数。

【讨论】:

【参考方案2】:

将钱存储为浮点数通常不是一个好主意,因为计算中可能会出现舍入错误。

考虑改用 DECIMAL(10,2)。

【讨论】:

无论精度如何,即使是 0.1 和 0.2 这样的数字也不可能用二进制浮点数表示。 en.wikipedia.org/wiki/Floating_point【参考方案3】:

存储为 3.5、3.50 甚至 3.500 真的很重要吗?

真正重要的是从数据库中检索后如何显示。

或者我在这里遗漏了什么?

也不要使用浮点数,使用小数。浮点数有各种舍入问题,而且不是很大。

【讨论】:

我确实提到了舍入问题。我的观点是他不应该担心它是如何存储的,而是它是如何显示的。您不会将财务信息存储到小数点后 2 位 - 汇率为 5,我们存储为 6,但仅显示为 2。 (删除了之前不相关的评论)。 +1 表示舍入的好点。【参考方案4】:

要存储值,您可以使用 DECIMAL(10,2) 字段,然后可以使用 FORMAT 函数:

SELECT FORMAT(`price`, 2) FROM `table` WHERE 1 = 1

【讨论】:

【参考方案5】:

为什么要将“3.50”存储到数据库中?就数据库而言,3.5 == 3.50 == 3.5000。

您的数字/日期/等的呈现和格式应该在应用程序中完成,而不是在数据库中。

【讨论】:

【参考方案6】:

如果您使用 DECIMAL 或 NUMERIC 类型,您可以将它们声明为例如 DECIMAL(18, 2) 这将强制 2 个小数,即使它们是 0。根据您期望的值有多大,您可以更改第一个的值参数。

【讨论】:

【参考方案7】:

二进制无法准确表示只有有限位数的浮点数。这不是数据丢失太多,而是实际上转换错误.. Here's the manual giving examples

您可以在浏览器中看到这一点,在这段代码 sn-p 中亲自查看。

<script>

    var floatSum = 0;

    // add 0.1 to floatSum 10 times
    for (var i=0; i<10; i++) 
        floatSum += 0.1;
    

    // if the repetative adding was correct, the floatSum should be equal to 1
    var expectedSum = 10*0.1; // 1

    // you can see that floatSum does not equal 1 because of floating point error
    document.write(expectedSum + " == " + floatSum + " = " + (expectedSum==floatSum) + "<br />");


    // --- using integers instead ---
    // Assume the example above is adding £0.10 ten times to make £1.00
    // With integers, we will use store money in pence (100 pence (also written 100p) in £1)

    var intSum = 0;

    // add 0.1 to floatSum 10 times
    for (var i=0; i<10; i++) 
        intSum += 10;
    

    // if the repetative adding was correct, the floatSum should be equal to 1
    var expectedSum = 10*10; // 100

    // you can see that floatSum does not equal 1 because of floating point error
    document.write(expectedSum + " == " + intSum + " = " + (expectedSum==intSum) + "<br />");
    document.write("To display as &pound; instead of pence, we can divide by 100 (presentation only) : &pound;" + intSum/100 + "<br />");
</script>

【讨论】:

以上是关于在mysql中存储金额的主要内容,如果未能解决你的问题,请参考以下文章

Java中存储金额用啥数据类型

从版本 5.0.3 开始,在 mysql 表的十进制字段中存储负数

从版本 5.0.3 开始,在 mysql 表的十进制字段中存储负数

mysql update,2个表,把第一个表中所有满足条件的字段值(金额),加总到另一个表的总金额里

JAVA中价格金额的存储类型

java中存储金额