正如这里所描述的,金钱类型似乎是不鼓励的。
我的应用程序需要存储货币,我应该使用哪种数据类型?数字、金钱还是浮动?
正如这里所描述的,金钱类型似乎是不鼓励的。
我的应用程序需要存储货币,我应该使用哪种数据类型?数字、金钱还是浮动?
当前回答
我保持所有的货币字段为:
数字(15,6)
使用这么多小数点数位似乎有些过分,但如果你需要处理多种货币,你就需要如此精确的转换。无论我呈现给用户什么,我总是存储到美元。这样,我就可以很容易地转换到任何其他货币,给定当天的汇率。
如果你只做一种货币,最糟糕的是你浪费了一些空间来存储一些0。
其他回答
我保持所有的货币字段为:
数字(15,6)
使用这么多小数点数位似乎有些过分,但如果你需要处理多种货币,你就需要如此精确的转换。无论我呈现给用户什么,我总是存储到美元。这样,我就可以很容易地转换到任何其他货币,给定当天的汇率。
如果你只做一种货币,最糟糕的是你浪费了一些空间来存储一些0。
你的消息来源绝不是官方的。这本书写于2011年,我甚至不认识作者。如果货币类型被官方“劝阻”,PostgreSQL会在手册中这样说——但它并没有。
要获得更多的官方来源,请阅读pgsql-general中的这篇文章(就在本周!),其中包括D’arcy J.M. Cain (money类型的原始作者)和Tom Lane等核心开发人员的声明:
关于最近版本改进的相关回答(和评论!):
Jasper Report:无法获取类“org.postgresql.util.PGmoney”的字段“x”的值
基本上,钱有它的(非常有限的)用途。Postgres Wiki建议在很大程度上避免它,除了那些狭义定义的情况。与数字相比,它的优势在于性能。
十进制只是Postgres中数字的别名,广泛用于货币数据,是一种“任意精度”类型。手册:
numeric类型可以存储数字数量非常大的数字。 特别推荐用于存储货币金额和其他 需要精确的数量。
就我个人而言,我喜欢将货币存储为表示美分的整数(如果分数美分从未出现的话)。这比上面提到的任何其他方法都更有效。
你的选择是:
Bigint:以分为单位存储金额。这就是EFTPOS事务所使用的。 Decimal(12,2):精确地存储小数点后两位的金额。这是大多数通用账本软件使用的。 浮动:糟糕的想法-不够准确。这是天真的开发人员使用的方法。
选项2是最常见和最容易使用的。将精度(在我的示例中为12,意味着总共有12个数字)设置为最适合您的大小。
请注意,如果您正在将计算结果(例如涉及汇率)的多个事务聚合到具有业务意义的单个值中,则精度应该更高,以提供准确的宏值;考虑使用decimal(18,8)之类的值,这样和是准确的,各个值可以四舍五入到精确的分值以便显示。
这不是一个直接的答案,而是一个例子,说明为什么浮动不是货币的最佳数据类型。
由于浮点数在内部的表示方式,它更容易出现舍入错误。
在我们自己的十进制系统中,除2和5之外的任何数都会有四舍五入误差,这两个数都是10的因数。在二进制中,它只有2而不是5,所以即使是“干净的”小数,比如0.2(1/5)也有风险。
如果你尝试以下方法,你就会看到这个结果:
select
0.1::float + 0.2::float as floats, -- 0.30000000000000004
0.1::numeric + 0.2::numeric as numerics --- 0.3
;
这就是那种让审计师抓狂的事情。
数值与强制2单位精度。永远不要使用float或float之类的数据类型来表示货币,因为如果你这样做,当财务报告的底线数字不正确时,人们会不高兴的。
据我所知,货币类型只是由于历史原因而被保留了下来。
举个例子:1伊朗里亚尔等于0.000030美元。如果您使用的小数位数少于5位,那么1个IRR将在转换后四舍五入为0美元。我知道我们在这里是均分的,但我认为在处理金钱问题时,越安全越好。