Jaybird中的Firebird NUMERIC / DECIMAL精度和比例

时间:2018-07-22 18:24:36

标签: jdbc decimal firebird numeric jaybird

我正在用Java的JDBC(Jaybird)测试Firebird NUMERIC / DECIMAL字段的行为。

使用FBResultSetMetaData检查列属性时(例如使用ResultSet.getObject方法进行SELECT * FROM NUMERICTEST查询),我得到了精度(FBResultSetMetaData.getPrecision)和小数位数({{1 }})完全与Firebird中的表定义中声明的相同,例如

FBResultSetMetaData.getScale

使用NUMERIC(3,2) field ... precision 3, scale 2 DECIMAL(3,2) field ... precision 3, scale 2 检查参数属性时(例如使用FBParameterMetaData方法进行PreparedStatement.setObject查询),对于相同的字段,我得到不同的精度值(INSERT INTO NUMERICTEST VALUES (?, ?))和缩放(FBParameterMetaData.getPrecision)。

FBParameterMetaData.getScale

我知道这些值在某种程度上与这些字段的内部数据库存储类型相对应(第一个示例中的NUMERIC(3,2) field ... precision 4, scale 2 DECIMAL(3,2) field ... precision 9, scale 2 ,第二个示例中的smallint?)。

integerFBResultSetMetaData与同一字段相关的行为不同的原因是什么?这是相当误导的。

Java 8 u 181,Jaybird 3.0.4,Firebird 2.5

1 个答案:

答案 0 :(得分:2)

问题在于,prepare本身仅为数字列(参数和结果集列)提供以下信息:

  • 类型(SQL_SHORTSQL_LONGSQL_INT64
  • 子类型(SMALLINT / INTEGER / BIGINT为0,NUMERIC为1,DECIMAL为2,
  • 规模
  • 以字节为单位的长度(2、4或8)

换句话说,声明的精度不可用。

对于参数,由于Firebird不提供允许发现实际精度的信息,因此无法知道与之比较或分配给该列的声明精度。因此,Jaybird使用列类型的最大精度(即SQL_SHORT:4,SQL_LONG:9和SQL_INT64:18)。

对于结果集列,Firebird可以在某些情况下提供基础列名称和表,而Jaybird使用此信息来查询元数据表以获取实际的精度信息。此信息并非始终可用,例如,计算/派生的列或涉及UNION的查询的列没有基础列名和表名。如果此信息不可用,Jaybird将以与参数相同的方式进行估算。

此信息的精度没有什么实际区别:即使声明为DECIMAL(6,2)(或NUMERIC(6,2))的列也可以存储和返回最大精度为9的值(即使考虑到事实,甚至为10) SQL_LONG是32位有符号整数)。对于Firebird中的所有意图和目的,DECIMAL(6,2)实际上是DECIMAL(9,2)。但是,我们决定提供可用的实际声明精度信息。

换句话说:Jaybird尽可能地精确,如果没有足够的信息,则性能会下降。

披露:我是Jaybird的开发人员之一。