jdbc - 通过 jdbc 查询结果不正确
问题描述
通过 jdbc driver snowflake-jdbc-3.12.5.jar 从 Snowflake 查询值时,结果不正确。
- Snowflake 中的表定义:
create table test_dob(DOB DECIMAL(38,3),REL DECIMAL(38,5));
insert into test_dob values(0.99, 0.99);
- 通过 jdbc 驱动程序 snowflake-jdbc-3.12.5.jar 从表 'test_dob' 中查询值;
.....
Connection conn = DriverManager.getConnection("jdbc:snowflake://XXXXX.aws.snowflakecomputing.com?db=testdbu", "user", "password");
......
String sql = "select dob,rel from test_dob";
PreparedStatement stmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
for (int j = 1; j < rs.getMetaData().getColumnCount() + 1; j++) {
//System.out.print(rs.getString(j) + ",");
System.out.print(rs.getDouble(j) + ",");
}
.......
查询结果如下:
0.9900000095367432,0.99,
可以得到第一列(“dob”)的查询值不正确,而第二列(“rel”)是正确的。
是驱动程序的错误吗?
解决方案
用于 SQL 类型的正确方法 是.ResultSet
DECIMAL
ResultSet::getBigDecimal(col)
相反,通过请求double
类型ResultSet::getDouble(col)
,您正在强制转换基础数字表示。
鉴于 SQL 十进制/数字数据类型中的不同比例 (3
和5
),每种情况的转换double
处理方式不同。对于较小的比例 ( 3
),由于其有限的位宽,对传输的值使用 small-int 类型,并且它的双精度转换实际上使用了一个浮点类型,该类型在其下向上转换为双精度。对于较大的比例(5
),使用常规整数并直接进行双精度转换。
jshell
这是幕后发生的事情的纯 Java(通过)表示
~> jshell
jshell> short sv = 990; // with scale 3
jshell> (double) ((float) sv / (float) 1000l)
$n ==> 0.9900000095367432
jshell> int iv = 99000; // with scale 5
jshell> (double) ((double) iv / (double) 100000l)
$n ==> 0.99
是驱动程序的错误吗?
//案例中double
所做的转换当然可以统一以改进行为,但除了用作测试示例之外,它不会解决问题。其他无法精确表示的键入数字将继续出现。byte
short
int
0.99
DECIMAL
double
虽然由于用于表示每种类型的位,转换会产生不同的结果,但从驱动程序正确性的角度来看,两者都是有效的,因为通过要求 adouble
代替 a BigDecimal
,您表明您不需要精确表示正在被取回。
如果需要精确/正确性(例如处理货币或在某些科学应用中),请改用以下内容:
System.out.print(rs.getBigDecimal(j) + ",");
要了解float
和double
类型的有损精度,请阅读:浮点数学是否损坏?
推荐阅读
- javascript - 数组列表获取替代结果的总和
- html - div 行没有正确对齐所有按钮
- regex - RegEx vb.net MatchCollection 充满了空字符串
- python-3.x - 我可以编写一个有效的函数来做到这一点吗?
- facebook - 如何在分享我的主页 URL 时告诉 Facebook 和 Twitter 显示我的主页图像?
- python - 通过集合中的订单号检索 mongodb 文档
- java - 如何在 Java/Kotlin 中以特定真实目录中的根目录创建虚拟文件系统?
- exception - What happens when a exception occurs in exception block
- azure - 使用 Golang 从 Azure Blob 存储下载文件时,得到“ curl Empty reply from server”,但文件是在后台下载的
- c++ - -fno-unwind-tables 和 -fno-asynchronous-unwind-tables 不起作用 NDK clang++