似乎不鼓励使用此处Money
描述的类型
我的应用程序需要存储货币,我应该使用哪种数据类型?数字、金钱还是浮点数?
您的消息来源绝不是官方的。它可以追溯到 2011 年,我什至不认识作者。如果货币类型被官方“劝阻”,PostgreSQL 会在手册中这样说 -它没有。
如需更官方的来源,请阅读pgsql-general 中的此线程(仅从本周开始!),其中包含核心开发人员的声明,包括 D'Arcy JM Cain(金钱类型的原作者)和 Tom Lane:
有关最近版本改进的相关答案(和评论!):
基本上,money
有其(非常有限的)用途。Postgres Wiki建议在很大程度上避免它,除了那些狭义的情况。优势numeric
在于性能。
decimal
只是numeric
Postgres 中的别名,广泛用于货币数据,是一种“任意精度”类型。手册:
该类型
numeric
可以存储具有非常多位数的数字。特别推荐用于存储货币数量和其他需要精确性的数量。
就个人而言,我喜欢将货币存储为integer
代表美分,如果小数美分永远不会出现(基本上是在货币有意义的地方)。这比任何其他提到的选项都更有效。
具有强制 2 个单位精度的数字。永远不要使用 float 或 float like 数据类型来表示货币,因为如果你这样做了,当财务报告的底线数字不正确 + 或 - 几美元时,人们会不高兴。
据我所知,货币类型只是出于历史原因而保留。
以此为例:1 伊朗里亚尔等于 0.000030 美元。如果您使用少于 5 个小数位,则 1 IRR 将在转换后四舍五入为 0 美元。我知道我们在这里分割里亚尔,但我认为在处理金钱时你永远不会太安全。
您的选择是:
bigint
:以美分存储金额。这是 EFTPOS 交易使用的。decimal(12,2)
: 存储精确到小数点后两位的金额。这是大多数总帐软件使用的。float
: 糟糕的想法 - 准确性不足。这是天真的开发人员使用的。选项 2 是最常见和最容易使用的。使精度(在我的示例中为 12,意味着总共 12 位数字)尽可能大或小,以最适合您。
请注意,如果您将计算结果(例如涉及汇率)的多个交易汇总为具有商业意义的单个值,则精度应该更高以提供准确的宏观值;考虑使用类似的东西,decimal(18, 8)
这样总和是准确的,并且各个值可以四舍五入到分精度以进行显示。
使用存储为的 64 位整数bigint
我建议使用微型美元(或类似的主要货币)。微意味着百万分之一,因此 1 微美元 = 0.000001 美元。
我将所有货币字段保留为:
numeric(15,6)
有这么多小数位似乎有点过分,但如果有哪怕是最微小的机会,您将不得不处理多种货币,那么您将需要如此高的精度来进行转换。无论我向用户展示什么,我总是以美元存储。考虑到当天的兑换率,我可以很容易地兑换成任何其他货币。
如果你只做一种货币,最糟糕的是你浪费了一点空间来存储一些零。
用于BigInt
将货币存储为以最小货币单位表示货币价值的正整数(例如,100 美分存储 1.00 美元或 100 存储 ¥100(日元,一种零十进制货币)。这就是 Stripe 所做的——一个全球电子商务最重要的金融服务公司。