所以我有以下问题。 我有一个通过jdbc连接到Redshift-DB的Java应用程序。执行一个简单的SELECT查询会产生一个不为空的ResultSet(我检查过)。
现在,当我尝试从此ResultSet提取数据时,即使先前的ResultSet.wasnull()返回false,并且该数据库中的手动检查也显示该记录中不包含该方法,该方法有时仍会返回null。该属性的空值。
示例代码:
private void test(){
ResultSet rs = null;
ResultSetMetaData rsmd = null;
String getTable = "SELECT * from myTable"; //
try(PreparedStatement prep = myConnection.prepareStatement(getTable
, ResultSet.TYPE_FORWARD_ONLY
)){
rs = prep.executeQuery();
rsmd = rs.getMetaData();
int columns = rsmd.getColumnCount();
while(rs.next()){ // loop over all rows
for(int col = 1; col <= columns; col++){
if(rs.wasNull())
System.out.println("NULL Value detected!");
System.out.println("Column Name: " + rsmd.getColumnName(col));
System.out.println("Column value: " + rs.getString(col));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
这在大多数情况下都有效,除了一些记录以外,rs.getString(col)只会导致为空(即使数据库中的数据类型为CHAR或VARCHAR)。并非所有的列都一定会发生这种情况(我已经看到正确地读取并打印了几列,直到wasnull()返回false的情况下,最终还是出现了空值。
到目前为止,我已经观察到ResultSet.getString(),ResultSet.getDate()和ResultSet.getTimestamp()的这种行为,但是从未提取任何类型的数字(getInt()...)。在所有这些情况下,我都要检查数据库以确保jdbc方法与数据类型匹配。
我尝试使用不同的驱动程序版本,而是尝试使用rs.getBytes(col),但结果仍然相同:我只是无法摆脱那些空值。
我还成功地执行了UNLOAD操作,将麻烦的表卸载到S3并手动检查了导出的csv文件。 UNLOAD运行没有任何问题,CSV对我来说看起来不错(所有值均符合预期)。
现在,我当然可以通过跳过出现它们的记录来手动处理那些“不需要的NULL”,但是我宁愿避免在不了解错误原因的情况下掩盖此类错误。
所以我的问题是:
我在代码中根本犯了错吗? jdbc / Redshift是否存在可能导致此问题的已知问题? 有人可以为我提供一些信息来源,也可以给我一些其他尝试的想法吗?
答案 0 :(得分:1)
来自ResultSet.wasNull()
的javadoc:
报告读取的最后一列是否具有SQL
NULL
的值。注意 您必须先在列上调用getter方法之一才能尝试 读取其值,然后调用方法wasNull
来查看 读取的值是SQLNULL
。返回:
true
,如果最后读取的列值是SQLNULL
,则返回false
换句话说,您应该在 之后阅读一列使用它。请注意,对于对象类型而言,调用wasNull
是没有意义的,因为对象获取器已经返回null
。
在使用原始getter(例如getInt()
)读取列时,应使用此方法,因为这些列将为0
值返回null
。然后,您可以使用wasNull()
来检查该值是真正的0
还是实际上的null
。
换句话说,将代码更改为:
while(rs.next()){ // loop over all rows
for(int col = 1; col <= columns; col++){
String value = rs.getString(col);
if(value == null)
System.out.println("NULL Value detected!");
System.out.println("Column Name: " + rsmd.getColumnName(col));
System.out.println("Column value: " + value);
}
}
或者,如果您确实要使用wasNull()
(但实际上不应该!):
while(rs.next()){ // loop over all rows
for(int col = 1; col <= columns; col++){
String value = rs.getString(col);
if(rs.wasNull())
System.out.println("NULL Value detected!");
System.out.println("Column Name: " + rsmd.getColumnName(col));
System.out.println("Column value: " + value);
}
}