我正在开发一个我正在使用 JDBC 和 Oracle11 的应用程序。
我的表tbltest
中有数十万条记录,我正在通过 JDBC 批量执行进行更新。因此,将其视为一个id =一个查询。
我的要求:我想跟踪哪些id
已成功更新,哪些在db中不存在。
以下是我的代码:
String sql = "UPDATE TBLTEST SET STATUS = 'CANCEL' WHERE ID = ?";
PreparedStatement preparedStatement = null;
Connection connection = getConnection(); // I'm getting this connection properly
preparedStatement = connection.prepareStatement(sql);
for (String id : idList) { // idList is a List of String being passed to my method
preparedStatement.setString(1, id);
preparedStatement.addBatch();
}
int[] affectedRecords = preparedStatement.executeBatch();
System.out.println("Records affected:"+Arrays.toString(affectedRecords));
int success = preparedStatement.getUpdateCount();
System.out.println(success + " Total updated");
我的记录已根据提供的idList
成功更新。根据{{3}} Javadoc,在affectedRecords
,我应该得到实际的不。由每个更新查询更新的记录,因为我没有得到任何异常。
相反,我只使用 -2 填充数组affectedRecords
。因此,如果idList
包含5个元素:
实际输出:
Records affected: [-2, -2, -2, -2, -2]
5 Total updated
预期输出:
Records affected: [1, 1, 1, 1, 1]
5 Total updated
我在互联网上搜索了这个问题,并发现了一些这样的帖子: this https://community.oracle.com/thread/3691652?start=0&tstart=0
但这些帖子中提供的解决方案对我没有帮助,因为我现在只使用 ojdbc6.jar 。
这个问题是否有解决方案或替代方案?
答案 0 :(得分:5)
我终于找到了它。该问题与PreparedStatement
。
根据Oracle here的Javadoc,当我使用PreparedStatement
时,我无法获得每个查询所影响的记录数。因此,当我将代码转换为Statement
时,它的效果非常好。
参考注释:
在Oracle标准批处理实施中更新计数如果a 语句批处理成功处理,然后是整数数组,或 update count数组,由executeBatch调用语句返回 对于批处理中的每个操作,始终有一个元素。在Oracle中 执行标准更新批处理,数组的值 要素如下:
对于准备好的声明批处理,无法知道该数字 数据库中受每个单独语句影响的行数 批量。因此,所有数组元素的值都为-2。根据 在JDBC 2.0规范中,值为-2表示该操作 成功但受影响的行数未知。
对于通用语句批处理,该数组包含实际更新 计数表示每个操作影响的行数。该 实际更新计数只能在通用的情况下提供 Oracle实现标准批处理中的语句。
对于可调用语句批处理,服务器始终返回值1 作为更新计数,与每个受影响的行数无关 操作
答案 1 :(得分:1)
-2
为SUCCESS_NO_INFO
,因此它不会告诉您批次中此元素的更新行数。但是从11.2.0.3开始,JDBC瘦驱动程序将告诉您批处理的每个元素的确切更新行数。这是该版本的关键新功能之一。它适用于PreparedStatement
。
答案 2 :(得分:0)
作为threads you link to describe,它不是ojdbc6.jar
vs ojdbc5.jar
的问题,而是与那些版本的旧版本相比的当前版本。
因此,请确保您获得最新版本的驱动程序:
如果使用java 5
运行程序,请选择ojdbc5.jarojdbc6.jar如果你用java 6运行程序
然后添加/替换orai18n.jar
还要确保java选择正确的版本,可能是使用java的-verbose
开关。