使用Java的PostgreSQL上的货币数据

使用Java的PostgreSQL上的货币数据,java,sql,postgresql,jdbc,currency,Java,Sql,Postgresql,Jdbc,Currency,我正在编写一个Java程序来挖掘货币兑换数据。数据可以有多个十进制数字,如“0.973047”。经过一些研究,我发现BigDecimal是适合Java的数据类型,但是我应该为PostgreSQL使用哪种数据类型呢 为了获得尽可能好的(和准确的)精度,您可以使用(或其别名DECIMAL),它具有高精度,允许您决定所需的精度 数字的 用户指定精度,精确到小数点前131072位;小数点后最多16383位 一般来说,货币不应该以浮点形式存储。最好的方法通常是将金额存储为最小允许大小的整数(例如,1美分)

我正在编写一个Java程序来挖掘货币兑换数据。数据可以有多个十进制数字,如“0.973047”。经过一些研究,我发现BigDecimal是适合Java的数据类型,但是我应该为PostgreSQL使用哪种数据类型呢

为了获得尽可能好的(和准确的)精度,您可以使用(或其别名
DECIMAL
),它具有高精度,允许您决定所需的精度

数字的

用户指定精度,精确到小数点前131072位;小数点后最多16383位


一般来说,货币不应该以浮点形式存储。最好的方法通常是将金额存储为最小允许大小的整数(例如,1美分),并将其格式化以供输入和显示。这基本上是SQL中固定精度的
十进制列所做的,但是如果将其转换回Java,仍然会有丢失精度的风险(例如,如果将最后允许的数字正好拆分一半会发生什么情况)

数值
/
十进制

作为,您希望使用类型作为任意精度类型

关于
数字
/
十进制
的两个要点:

  • 请仔细阅读,以了解您应该指定小数位数,以避免默认小数位数为0,这意味着删除小数部分的整数值。虽然这是Postgres偏离标准SQL的地方之一(让您可以扩展到实现极限)。因此,未能指定比例是一个糟糕的选择
  • 根据SQL标准,SQL类型<代码>数值<代码>和<代码>十进制<代码>非常接近,但不完全相同。在中,您为
    数值
    指定的精度将得到尊重,而对于
    十进制
    则允许数据库服务器添加超出您指定精度的额外精度。这里Postgres又一次偏离了标准,将
    数字
    十进制
    作为等价物
条款:

  • 精度是数字中的总位数
  • 小数位数是小数点(小数点)右侧的位数
  • (精度-刻度)=小数点左侧的位数(整数部分)
明确项目的精度和比例规格:

  • Big
    精度必须足够大,以处理将来可能需要的较大数字。这意味着…也许你的应用程序今天的工作金额为数千美元,但在未来必须执行数百万美元的汇总报告
  • Small
    出于某些会计目的,您可能需要存储最小货币金额的一小部分。意思是…超过小数点后3或4位,而不是一便士所需的2位
避免
MONEY
type Postgres也提供了一种类型。这听起来可能是对的,但在大多数情况下可能不是最好的。一个缺点是,对于
MONEY
比例是由数据库范围的配置设置设置的。因此,当您切换服务器或进行其他更改时,该设置很容易发生危险的变化。此外,您无法控制特定列的设置,而可以在
NUMERIC
类型的每列上设置比例。最后,
MONEY
不是本文所示的标准SQL。Postgres包括
MONEY
,方便人们从其他数据库系统移植数据

移动小数点 有些人采用的另一种选择是移动小数点,只存储在大整数数据类型中

例如,如果将美元存储到便士,将任何给定的小数乘以100,转换为整数类型,然后继续。例如,$123.45成为整数12345

这种方法的好处是执行时间更快。当对整数执行
sum
等操作时,速度非常快。整数的另一个好处是更少的内存使用

我觉得这种方法烦人、令人困惑,而且有风险。恼人是因为电脑应该为我们工作,而不是与我们作对。风险很大,因为一些程序员或用户可能会忽略乘/除转换回小数,从而给出错误的结果。如果在一个没有精确分数支持的系统中工作,这种方法可能是一种可接受的解决方法

在SQL和Java中使用
decimal
/
NUMERIC
时,我看不出移动小数点有什么好处

舍入&
NaN
在应用程序的编程中,以及在Postgres服务器端进行的任何计算中,要非常小心,注意小数点的舍入和截断。并测试是否意外弹出

无论是app还是Postgres,为了赚钱,都要避免使用数据类型浮点运算是为了提高运算速度而设计的,但以牺牲精度为代价。计算可能会导致小数部分出现看似疯狂的额外数字。不适用于财务/金钱或其他需要准确性的用途

BigDecimal
是的,在Java中,您希望将其作为任意精度类型
BigDecimal
速度较慢,占用更多内存,但可以准确存储您的金额。SQL
NUMERIC
/
DECIMAL
应映射到
BigDecimal
,如前所述

BigDecimal
是Java最好的东西之一。我不知道有任何其他平台具有类似的类,尤其是一个经过多年来的重大改进和修复,实现和磨练得如此之好的平台

使用
BigDecimal
肯定比使用
float
double
慢。但在现实世界的应用程序中,我怀疑你的金钱计算结果会有任何偏差