jdbc ResultSet.get <datatype>返回null

时间:2018-07-23 11:47:42

标签: java jdbc amazon-redshift

所以我有以下问题。 我有一个通过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是否存在可能导致此问题的已知问题? 有人可以为我提供一些信息来源,也可以给我一些其他尝试的想法吗?

1 个答案:

答案 0 :(得分:1)

来自ResultSet.wasNull()的javadoc:

  

报告读取的最后一列是否具有SQL NULL的值。注意   您必须先在列上调用getter方法之一才能尝试   读取其值,然后调用方法wasNull来查看   读取的值是SQL NULL

     

返回:
  true,如果最后读取的列值是SQL NULL,则返回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);
    }
}