我正在用Java中的JDBC (Jaybird)测试Firebird数字/十进制字段的行为。
当使用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我知道这些值在某种程度上对应于这些字段的内部db存储类型(在第一个示例中为smallint,在第二个示例中为integer )。
当涉及同一领域时,FBResultSetMetaData和FBParameterMetaData行为不同的原因是什么?这很有误导性。
Java 8 u 181、Jaybird 3.0.4、Firebird 2.5
发布于 2018-07-23 15:04:00
问题是,准备本身只为数值列(参数列和结果集列)提供下列信息:
SQL_SHORT、SQL_LONG、SQL_INT64、SQL_INT128)SMALLINT/INTEGER/BIGINT/INT128,1用于NUMERIC,2用于DECIMAL,换句话说,声明的精度不可用。
对于参数,无法知道与其进行比较或分配的列的声明精度,因为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位有符号整数这一事实也是如此)。对于火鸟的所有意图和目的,DECIMAL(6,2)实际上是一个DECIMAL(9,2)。但是,我们决定在获得实际声明的精确信息时提供该信息。
换句话说,Jaybird是尽可能精确的,如果它没有足够的信息,它就会优雅地退化。
披露:我是Jaybird的开发者之一。
https://stackoverflow.com/questions/51468049
复制相似问题