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
?)。
FBResultSetMetaData
和 FBParameterMetaData
在涉及同一字段时表现不同的原因是什么?这是相当具有误导性的。
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 的开发者之一。
我正在 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
?)。
FBResultSetMetaData
和 FBParameterMetaData
在涉及同一字段时表现不同的原因是什么?这是相当具有误导性的。
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 的开发者之一。