使用Informix 12.10FC5DE和JDBC.4.10.JC5DE,我正在尝试编写一个Java程序,它将在表上执行“受控”删除。 将记录包含该表的数据库,并且该表具有“锁定模式行”。 程序将收到要删除的最大行数,并且每X行执行一次定期提交(以限制锁的数量并防止长事务)。
使用SPL,我可以使用hold声明一个游标并使用“delete where current of”执行foreach循环。
使用JDBC,我可以使用resultSet
方法.next()
和.deleteRow()
来执行我想要的操作(我将连接和语句设置为不自动提交或在提交时关闭resultSet )。
它工作正常,但它很慢(在JDBC下发送类似“DELETE FROM TABLE WHERE COLUMN =?”)。
我的代码类似于以下内容:
Class.forName("com.informix.jdbc.IfxDriver");
Connection conn = DriverManager.getConnection(url);
conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
conn.setAutoCommit(false);
String cmd = "SELECT id FROM teste_001 FOR UPDATE;";
Statement stmt = conn.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE,
ResultSet.HOLD_CURSORS_OVER_COMMIT);
stmt.setFetchSize(100);
stmt.setCursorName("myowncursor");
ResultSet resultados = stmt.executeQuery(cmd); // Get the resulSet and cursor
int maximo = 2000;
int passo = 100;
int cTotal = 0;
int cIter = 0;
cmd2 = "DELETE FROM teste_001 WHERE CURRENT OF " +
resultados.getCursorName();
PreparedStatement stmtDel2 = conn.prepareStatement(cmd2);
while (resultados.next())
{
if (cIter < maximo)
{
int resultCode2 = stmtDel2.executeUpdate();
if (resultCode2 == 1)
{
cTotal++;
}
cIter++;
if ((cIter % passo) == 0)
{
conn.commit(); // Perform periodic commit
}
}
else
{
break; // maximum number of rows reached
}
}
conn.commit(); // Perform final commit
stmtDel2.close();
resultados.close();
stmt.close();
conn.close();
问题是,当我执行第一次定期提交时,我在尝试下一次删除时出现此错误:
java.sql.SQLException: There is no current row for UPDATE/DELETE cursor.
SQLCODE = -266 ; MESSAGE: There is no current row for UPDATE/DELETE cursor. ; SQLSTATE = 24000
即使我设置了“HOLD_CURSORS_OVER_COMMIT”,似乎光标正在关闭。
有没有人知道我尝试使用JDBC是否可行?
编辑:
自informix支持IBM DRDA协议以来,我在测试informix实例上配置了drda侦听器,并使用了DB2 UDB JDBC Universal Driver。
代码几乎相同,只有驱动程序更改:
Class.forName("com.ibm.db2.jcc.DB2Driver");
使用DRDA驱动程序,光标在提交时保持打开状态,程序按预期运行。在informix实例上跟踪会话我得到这种类型的声明:
DELETE FROM test_001 WHERE CURRENT OF SQL_CURSH600C1
因此,informix使用DRDA驱动程序支持“HOLD_CURSORS_OVER_COMMIT”,但我仍然无法使用“ifxDriver”。