182

似乎不鼓励使用此处Money描述的类型

我的应用程序需要存储货币,我应该使用哪种数据类型?数字、金钱还是浮点数?

4

6 回答 6

149

您的消息来源绝不是官方的。它可以追溯到 2011 年,我什至不认识作者。如果货币类型被官方“劝阻”,PostgreSQL 会在手册中这样说 -它没有

如需更官方的来源,请阅读pgsql-general 中的此线程(仅从本周开始!),其中包含核心开发人员的声明,包括 D'Arcy JM Cain(金钱类型的原作者)和 Tom Lane:

有关最近版本改进的相关答案(和评论!):

基本上,money有其(非常有限的)用途。Postgres Wiki建议在很大程度上避免它,除了那些狭义的情况。优势numeric在于性能

decimal只是numericPostgres 中的别名,广泛用于货币数据,是一种“任意精度”类型。手册

该类型numeric可以存储具有非常多位数的数字。特别推荐用于存储货币数量和其他需要精确性的数量。

就个人而言,我喜欢将货币存储为integer代表美分,如果小数美分永远不会出现(基本上是在货币有意义的地方)。这比任何其他提到的选项都更有效。

于 2013-03-31T12:56:44.367 回答
114

具有强制 2 个单位精度的数字。永远不要使用 float 或 float like 数据类型来表示货币,因为如果你这样做了,当财务报告的底线数字不正确 + 或 - 几美元时,人们会不高兴。

据我所知,货币类型只是出于历史原因而保留。

以此为例:1 伊朗里亚尔等于 0.000030 美元。如果您使用少于 5 个小数位,则 1 IRR 将在转换后四舍五入为 0 美元。我知道我们在这里分割里亚尔,但我认为在处理金钱时你永远不会太安全。

于 2013-03-31T11:03:56.853 回答
101

您的选择是:

  1. bigint:以美分存储金额。这是 EFTPOS 交易使用的。
  2. decimal(12,2): 存储精确到小数点后两位的金额。这是大多数总帐软件使用的。
  3. float: 糟糕的想法 - 准确性不足。这是天真的开发人员使用的。

选项 2 是最常见和最容易使用的。使精度(在我的示例中为 12,意味着总共 12 位数字)尽可能大或小,以最适合您。

请注意,如果您将计算结果(例如涉及汇率)的多个交易汇总为具有商业意义的单个值,则精度应该更高以提供准确的宏观值;考虑使用类似的东西,decimal(18, 8)这样总和是准确的,并且各个值可以四舍五入到分精度以进行显示。

于 2013-03-31T11:18:06.077 回答
40

使用存储为的 64 位整数bigint

我建议使用微型美元(或类似的主要货币)。微意味着百万分之一,因此 1 微美元 = 0.000001 美元。

  • 易于使用并与每种语言兼容。
  • 足够的精度来处理一分钱。
  • 适用于非常小的单位定价(如广告展示或 API 费用)。
  • 比字符串或数字更小的存储数据大小。
  • 通过计算轻松保持准确性并在最终输出中应用舍入。
于 2018-07-09T05:34:11.720 回答
32

我将所有货币字段保留为:

numeric(15,6)

有这么多小数位似乎有点过分,但如果有哪怕是最微小的机会,您将不得不处理多种货币,那么您将需要如此高的精度来进行转换。无论我向用户展示什么,我总是以美元存储。考虑到当天的兑换率,我可以很容易地兑换成任何其他货币。

如果你只做一种货币,最糟糕的是你浪费了一点空间来存储一些零。

于 2015-10-16T18:52:47.217 回答
14

用于BigInt将货币存储为以最小货币单位表示货币价值的正整数(例如,100 美分存储 1.00 美元或 100 存储 ¥100(日元,一种零十进制货币)。这就是 Stripe 所做的——一个全球电子商务最重要的金融服务公司。

资料来源:请参阅https://stripe.com/docs/currencies上的“零十进制货币”

于 2020-05-29T14:35:57.827 回答