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

标签 jdbc decimal firebird numeric jaybird

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

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

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

最佳答案

问题是准备本身仅提供数字列的以下信息(参数和结果集列):

  • 类型(SQL_SHORTSQL_LONGSQL_INT64SQL_INT128),
  • 子类型(0 表示 SMALLINT/INTEGER/BIGINT/INT128,1 表示 NUMERIC 和 2 代表 DECIMAL
  • 规模,
  • 长度(以字节为单位)(2、4、8 或 16)。

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

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

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

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

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

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

关于jdbc - Jaybird 中的 Firebird NUMERIC/DECIMAL 精度和比例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51468049/

相关文章:

java - 从 java 连接到 MS Access

java - 在Java中检查BigDecimal小单位的最佳方法

c# - Fluent Nhibernate 按条件映射到不同的列

c++ - 在 Qt 中连接到 Firebird 数据库

java - 如何在 Play 中切换生产和开发数据库配置?

mysql - docker pentaho mysql驱动问题

java - 我可以在 Spring Roo 中使用 MS Access JDBC 驱动程序吗?

r - 在R中将十六进制转换为十进制

python - python中是否有将IP地址转换为十进制数的函数?

firebird - 编写 Firebird UDF 返回 OCTETS