SQLException:执行while(rs.getNext())时截断的fetched列值被截断

时间:2009-01-19 04:33:23

标签: java sql database oracle

我有一个程序可以使用相当简单的查询从Oracle 10g(10.2.0.3)中提取大型数据集。您几乎可以将查询/逻辑称为排序的“导出”,因为它从具有最小where子句的表中选择列(即,它返回大部分(如果不是全部)行)。

[Java]代码是我们所见过的样板:

Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
    con = getConnection(Person);
    pstmt = con.prepareStatement(
            "SELECT ID, FIRST_NAME, LAST_NAME, ... FROM PERSON WHERE ...");
    rs = pstmt.executeQuery();
    while (rs.next()) {
        // write the data to a file
    }
}
finally {
    if (rs != null) try { rs.close(); } catch (Exception e) { }
    if (pstmt != null) try {pstmt.close(); } catch (Exception e) { }
    if (con != null) try { con.close() ; } catch (Exception e) { }
}

getConnection是我自己的方法,它将Connection对象返回到用于“PERSON”表的Oracle数据库。这感觉就像一个平凡的编程问题,但我已经多次编写这样的代码,从来没有遇到过这个问题。

我收到一个java.sql.SQLException:ORA-01406:在while(rs.next())行上截断了fetched列值。我读过的Oracle文档说“FETCH操作被强制截断一个字符串。”它建议使用更大的列缓冲区来容纳最大的列。但这没有意义。在上面代码注释为“将数据写入文件”的部分中,我只是用rs.getBigDecimal(“ID”),rs.getString(“FIRST_NAME”等等)编写每一列,事实上,我可以使用与ResultSet无关的空while循环重现该区域。也就是说,只是遍历ResultSet会导致抛出SQLException。

返回的数据集大小应约为100万行。在循环中大约600,000行/次迭代后,我得到异常。有什么想法吗?

4 个答案:

答案 0 :(得分:1)

PERSON是桌子还是视图?

在某些时候,Java必须为数据设计一个数据长度。而且我猜它做错了。首先,逐个删除列,以便您可以确定哪个列出错。然后可以通过块中的数据(例如1-100000,100001-200000等)来查找导致错误的块。然后缩小块(100000-150000等),直到找到导致问题的单行。通过查看该行,可能很明显问题是什么。如果没有,请尝试使用DUMP函数查看数据中的字节。

数字列中的数据可能与列定义不对应。这通常是一个错误,可能是磁盘损坏,有时是通过OCI创建的奇怪数据。你可以尝试做一个

SELECT COUNT(*) FROM PERSON WHERE ID != TRUNC(ID); 

如果您的数据库使用多字节字符集,则可能会使字符串混淆。如果字符串中有非常规字符(例如ASCII 0-31)

答案 1 :(得分:0)

对我而言,首先要做的是查看“有缺陷”的数据,修改循环以显示触发异常的行。

答案 2 :(得分:0)

首先在查询上尝试getMaxFieldSize,这样你就可以清楚地知道最大的feild大小是多少。我不是Oracle程序员(PostgreSQL),但我知道Oracle应该有一个(如果不是最好的话)元数据支持。修改您的SQL查询,并限制最大字段大小。那至少会让你在那里一半。

  

public int getMaxFieldSize()                       抛出SQLException

Returns the maximum number of bytes allowed for any column value.
     

此限制是最大数量   可以为任何返回的字节   列值。该限制仅适用   到BINARY,VARBINARY,LONGVARBINARY,   CHAR,VARCHAR和LONGVARCHAR   列。如果超过限制,   多余的数据被默默地丢弃。

Returns:
    the current max column size limit; zero means unlimited
Throws:
    SQLException - if a database access error occurs

答案 3 :(得分:0)

另外,您应该考虑使用Apache Commons DBUtils来关闭资源。这将允许您用一行替换finally子句的内容:

DBUtils.closeQuietly(con, pstmt, rs);