货币/货币价值 - 如何存储在DB&使用JSON转移?

时间:2013-05-02 12:19:29

标签: json postgresql currency

在数据库中存储货币/货币值,在服务器端应用程序中处理它们,最后通过JSON API将它们发送到浏览器的最佳做法是什么?

我已经找到了两种方法,但我不确定如何权衡专业人士和缺点:

将值存储为最小货币单位的整数

  • 基本上这意味着数据库会以货币/ paise / shillings /等存储货币价值。
  • 服务器端应用程序会将此值映射到常规整数变量。
  • JSON API将该值表示为常规JSON号。
  • 这种方法的缺点是,在向用户显示货币价值之前必须不断除以100,并且在存储任何用户输入之前总是乘以100。
  • 可能的陷阱:您如何定义最小的货币单位?它是基于两个小数点还是四个小数点?是否有任何货币没有100:1的比率,即100美分= 1美元。

将值存储为十进制/数字,具有固定的精度&规模

  • DB将货币值存储为具有固定精度&的十进制/数字类型。规模,例如。 NUMERIC(10,2)
  • 服务器端应用程序将这些映射到特殊对象,这可以保持精度和安全性。跨计算进行扩展,例如。 Ruby中的BigDecimal
  • JSON API将这些值作为字符串而不是数字进行交换。因为数字会被JSON解析器自动解析为浮点数,从而导致精度损失。
  • 这种方法的缺点是服务器端的所有计算都需要在盒装数据类型中发生(可能更慢)并且JSON解析器需要知道某些字符串实际上不是字符串的事实,但是数值。
  • 这样做的好处是你不需要经常乘以除以100。

是否有普遍接受的最佳做法?

1 个答案:

答案 0 :(得分:4)

这两种做法都有两个额外的问题。

首先,并非所有货币都需要两位小数。很多人需要三个。还有更多需要零。以及一些特定于字段的应用,例如财务和外汇,需要5或6。

其次,某些货币对于次级名称具有丰富的转换率。例如,老派卢比兑换成16个annas,64个paise或192个馅饼。幸运的是,只有两个国家保留这种疯狂的转换率,如果维基百科可以通过 - 毛里塔尼亚1 ouguiya = 5 khoums,马达加斯加1 ariary = 5 iraimbilanja。

http://en.wikipedia.org/wiki/Decimalisation

但重点是,如果您打算本地化您的应用,那么您的假设不应该过于以美国为中心。至少,考虑一下你有0,2和3位小数的用例,并咀嚼一下如果你去国际,你想要采取什么样的路径。以防万一。

另外,还要注意Postgres中的numeric类型可以在不指定精度的情况下存储。它没有更多的空间,因为当它太大时,它将驻留在扩展存储中。并且,就像varchar更好于varchar(n)一样,它会更快,因为在存储数字时你会跳过内置的精确检查(在这种情况下,确实需要保持正确) )。

至于你所描述的两种方法中哪一种是最好的,我已经看到了更多的第二种 - 以简化形式。

我强调三点:

  1. 在生成帐户和报告时,为了不引入舍入错误,在数据库中将货币存储为numeric(有或没有精度)是有意义的。 (也有一种内置的金钱类型,但我从来没有看到它在实践中用于各种非常有效的原因。)

  2. 如果你真的需要溢出bigint或双精度浮点数的精度,那么速度应该是你最不担心的(后者的js和json用于浮点数,如果内存供应)。如果是这种情况,那么任意精确数学就是从一端到另一端的方式。

  3. 操纵典型货币金额的典型应用程序永远不会遇到这些溢出限制。在这里冷静一下。除非您计划以数十亿美元存储金额,否则将无界数字转换为字符串并返回以在json中传递它们表明您过度设计了应用程序。如果是这种情况,只需坚持使用双精度浮动并运送您的应用程序。