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

Firebird NUMERIC/DECIMAL precision and scale in Jaybird

我正在 Java.

JDBC (Jaybird) 中测试 Firebird NUMERIC / DECIMAL 字段行为

当使用 FBResultSetMetaData 检查列属性时(使用 ResultSet.getObject 方法进行例如 SELECT * FROM NUMERICTEST 查询)我得到精度 (FBResultSetMetaData.getPrecision) 和比例 (FBResultSetMetaData.getScale) 与 Firebird 中的 table 定义完全一致,例如

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,第二个示例中的 integer?)。

FBResultSetMetaDataFBParameterMetaData 在涉及同一字段时表现不同的原因是什么?这是相当具有误导性的。

Java 8 u 181, Jaybird 3.0.4, Firebird 2.5

问题是 prepare 本身只为数字列(参数和结果集列)提供以下信息:

  • 类型 (SQL_SHORT, SQL_LONG, SQL_INT64),
  • 子类型(SMALLINT/INTEGER/BIGINT 为 0,NUMERIC 为 1,DECIMAL 为 2,
  • 规模
  • 字节长度(2、4 或 8)

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

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

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

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

换句话说:Jaybird 尽可能精确,如果没有足够的信息,它会优雅地退化。

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