【问题标题】:Best data type to store money values in MySQL在 MySQL 中存储货币值的最佳数据类型
【发布时间】:2012-10-13 09:08:05
【问题描述】:

我想在 MySQL 数据库中存储许多记录。它们都包含货币价值。但我不知道每个要插入多少位。
为此,我必须使用哪种数据类型?
VARCHARINT(或其他数字数据类型)?

【问题讨论】:

标签: mysql sqldatatypes currency


【解决方案1】:

因为金钱需要精确的表示,所以不要使用像float 这样的近似数据类型。您可以为此使用定点数值数据类型

decimal(15,2)
  • 15 是精度(值的总长度包括小数位)
  • 2 是小数点后的位数

MySQL Numeric Types:

当需要保持精确的精度时使用这些类型,例如 货币 数据。

【讨论】:

  • 在这种情况下,十进制和数字数据类型有什么区别?
  • 在 MySQL 中 decimalnumeric 是一样的。
  • 我个人使用numeric(19,4) 记录财务记录,让您可以更好地进行游戏并轻松接受新请求。
  • 我同意 YahyaE,小数越多越好。有些货币通常使用 3 个小数位,例如巴林、约旦或科威特第纳尔,因此您至少需要 3 个。四或五个更好。
  • @EdwinHoogerbeets 不是会计师……但在英国经营一家小企业……我记得很久以前在某个地方读到过,即使是英镑、美元,货币数字也应该存储到小数点后 4 位等,以便某些计算实际上可能使用某些晦涩的会计上下文的最后 2 位小数。 Wd 需要会计师来确认/反驳。
【解决方案2】:

你可以使用DECIMALNUMERIC两者都是一样的

DECIMAL 和 NUMERIC 类型存储精确的数字数据值。当保持精确的精度很重要时使用这些类型,例如货币数据。在 MySQL 中,NUMERIC 被实现为 DECIMAL,因此以下关于 DECIMAL 的注释同样适用于 NUMERIC。 :MySQL

DECIMAL(10,2)

Good read

【讨论】:

  • 可能令人困惑,但您的屏幕截图与您的答案文本(精度、比例)不匹配。
  • 我使用 decimal(10,2) 作为我的货币价值,但是当我输入 867,000.00 之类的值时,它会保存为 867。我做错了什么?
  • @codeinprogress 你的货币价值中有一个逗号......如果它以同样的方式进入数据库。 Mysql会从逗号位置开始截断
【解决方案3】:

我更喜欢使用BIGINT,并将值存储在乘以100,这样它就会变成整数。

例如,要表示93.49的货币值,该值应存储为9349,同时显示该值我们可以除以100并显示。这将占用更少的存储空间。

注意:
大多数情况下,我们不执行currency * currency 乘法,以防万一,如果我们这样做,则将结果除以 100 并存储,以便它返回正确的精度。

【讨论】:

  • 我记得在我的计算机系统大学课程中,一位教授告诉过我类似的话。我被教导最精确的方法是通过乘以 100 并保存为整数并除以 100 以将其显示给用户来存储在便士(或美分)中。我想这对数据库系统的准确性和性能有好处。
  • 相比DECIMAL有什么优势?你创造了将便士兑换成美元的需求,如果你在某个时候忘记了它,就会有祸了。
  • 空间是唯一的优势,但是是的,我们在使用此功能时需要更加小心。
  • 如果不是很明显:如果您以分数美分存储钱(例如,$0.005$0.12345),请小心使用除垢方法,因为它们在相乘后不会减少为整数乘以 100。如果您知道值的精度,很明显最好的选择是使用 DECIMAL。但是,如果您不知道精度(如我的示例中所示),那么……FLOAT 是否合适?
  • 这种方法的一个优势在于使用像 JavaScript 这样使用 IEEE-754 来存储浮点数的语言。本规范不保证 0.1 + 0.2 === 0.3 为真。将货币存储为整数可以确保您的应用程序不会发生这种错误。虽然这可能不是最好的解决方案。我在研究解决方案时到达了这个页面,但我还没有完成。
【解决方案4】:

这取决于你的需要。

通常使用DECIMAL(10,2) 就足够了,但如果您需要更精确的值,您可以设置DECIMAL(10,4)

如果您使用较大的值,请将 10 替换为 19

【讨论】:

  • 我使用 decimal(10,2) 作为我的货币价值,但是当我输入 867,000.00 之类的值时,它会保存为 867。我做错了什么?
  • @codeinprogress 使用了错误的语言环境/小数点分隔符?
  • @codeinprogress 您正在使用 , 进行数字分组。不要那样做。切勿使用逗号或点进行数字分组。
【解决方案5】:

如果您的应用程序需要处理高达一万亿的货币价值,那么这应该可行:13,2 如果您需要遵守 GAAP(公认会计原则),请使用:13,4

通常在将输出四舍五入为 13.2 之前,您应该将您的货币价值加总为 13.4。

【讨论】:

【解决方案6】:

在被问到这个问题时,没有人考虑过比特币的价格。在 BTC 的情况下,使用DECIMAL(15,2) 可能是不够的。如果比特币涨到 100,000 美元或更多,我们至少需要DECIMAL(18,9) 来支持我们的应用程序中的加密货币。

DECIMAL(18,9) 在 MySQL (4 bytes per 9 digits) 中占用 12 字节空间。

【讨论】:

  • > 一个比特币可以分成小数点后 8 位。因此,0.00000001 BTC 是一笔交易中可以处理的最小金额。我想你的意思是 8 而不是 9?
  • 我知道,但是 9 占用与 8 相同的磁盘空间。来自 MySQL 文档:“DECIMAL 列的值使用二进制格式存储,将 9 个十进制数字打包成 4 个字节”
  • 对不起,现在我明白了。谢谢。
【解决方案7】:

我们使用double

*喘气*

为什么?

因为它可以表示任何 15 位数字对小数点的位置没有限制。全部只有区区 8 个字节!

所以它可以表示:

  • 0.123456789012345
  • 123456789012345.0

...以及介于两者之间的任何东西。

这很有用,因为我们处理的是全球货币,而double 可以存储我们可能会遇到的各种小数位数。

单个 double 字段可以代表日元的 999,999,999,999,999,美元的 9,999,999,999,999.99,甚至比特币的 9,999,999.99999999

如果您尝试对 decimal 执行相同操作,则需要 decimal(30, 15),它占用 14 个字节。

注意事项

当然,使用double 并非没有注意事项。

但是,这并不是某些人倾向于指出的准确性损失。尽管double 本身可能内部不精确到以 10 为底的系统,但我们可以通过将我们从数据库中提取的值四舍五入使其精确到它的有效小数位.如果需要的话。 (例如,如果要输出,则需要以 10 为基数的表示。)

需要注意的是,任何时候我们使用它进行算术运算时,我们都需要在之前对结果进行标准化(通过将其四舍五入到有效的小数位):

  1. 对其进行比较。
  2. 将其写回数据库。

另一种警告是,与decimal(m, d) 不同,数据库将阻止程序插入超过m 位数的数字,double 不存在此类验证。一个程序可以插入一个用户输入的 20 位数的值,它最终会被默默地记录为不准确的数量。

【讨论】:

  • 我第一次看到这样的答案,很有趣。问:如果我将 1.41 之类的浮点数写入数据库,出于某种原因,我需要将它乘以 mysql 中的某个巨大数字,例如 1.000.000.000.000。四舍五入的结果会不会是:1.410.000.000.000?
  • @roelleor 为使结果恰好为 1,410,000,000,000(逗号作为千位分隔符),假定输入为 1.410000000000(小数点后 12 位有效),但乘以 1,000,000,000,000(即 13 位有效数字)小数点左侧)意味着我们正在处理至少 25 位有效数字。这远远超过了双倍可用的 15 个,所以在设计方面我认为它会很糟糕。
【解决方案8】:

如果需要 GAAP 合规性或您需要 4 个小数位:

十进制(13, 4) 其中支持的最大值为:

999,999,999.9999 美元

否则,如果 2 位小数就足够了: 小数(13,2)

源代码:https://rietta.com/blog/best-data-types-for-currencymoney-in/

【讨论】:

    【解决方案9】:

    这确实取决于程序员的偏好。我个人使用:numeric(15,4) 以符合公认会计原则 (GAAP)

    【讨论】:

    • 它与“程序员的偏好”或您“个人使用的”无关。它由需要十进制基数的问题域决定。这不是程序员可以行使自己的个人喜好的问题。
    【解决方案10】:

    尝试使用

    Decimal(19,4)
    

    这通常也适用于所有其他数据库

    【讨论】:

      【解决方案11】:

      将钱存储为BIGINT 乘以 100 或更多,理由是使用更少的存储空间在所有“正常”情况下都是没有意义的。

      【讨论】:

        【解决方案12】:

        乘以 10000 并存储为 BIGINT,如 Visual Basic 和 Office 中的“货币”。见https://msdn.microsoft.com/en-us/library/office/gg264338.aspx

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-14
          • 2011-10-19
          • 2017-11-21
          • 2010-11-08
          相关资源
          最近更新 更多