我有一个程序可以使用相当简单的查询从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行/次迭代后,我得到异常。有什么想法吗?
答案 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);