更新ResultSet中的行会生成错误:'发生值冲突'

时间:2015-11-25 13:55:58

标签: java oracle jdbc

我们公司写了一个相当复杂的程序来将数据从一个数据库传输到另一个数据库。应该传输的数据标记为' 1'某个列中的(String / Varchar2)。 我无法解释为什么这不仅仅是数字或布尔字段。我想这是一个历史性的残余。

ResultSet的创建如下:

Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet extractedData = stmt.executeQuery(sql);

如果发现了某些内容,请将其解压缩到文件中:

if (extractedData.next()) {
    writeDataToFile(extractedData)
}

简化的写作方法如下所示:

private void writeDataToFile(ResultSet extractedData) {

    extractedData.beforeFirst(); // because of the next() we called before
    writeLines(extractedData);

}

writeLines()中,我们正在遍历整个ResultSet并将其写入文件。

完成后,我们可以通过将列中的值设置为' 0'来标记传输的数据。如果发生异常,我们不能提前做到。

extractedData.beforeFirst();
while (extractedData.next()) {      
    extractedData.updateString(updateColumn, "0");
    extractedData.updateRow();
}

我们怀疑updateRow()导致SQLException发出消息'发生价值冲突'

很少发生这种情况。每个月都会像这样提取数百万条记录,只有大约2条记录会抛出此错误。

有没有人知道可能导致这种情况的原因?

1 个答案:

答案 0 :(得分:1)

ResultSet未在表行上建立任何锁定。另一个过程可以改变它。当oracle中的rowid出现问题时会出现异常 如何复制这种行为。

create table example1 (id number, value varchar2(10));
insert into example1 values(1,'a');
insert into example1 values(2,'b');
insert into example1 values(3,'c');
insert into example1 values(4,'d');
insert into example1 values(5,'e');
commit;

和java APP。 deleteRow - 打开新的oracle会话并从表中删除行。

public class Updatable {
    public static void main(String[] args) throws SQLException, Exception {
        Connection conn = ConnectionDefinition.getOracleConnection();
        Statement  createStatement = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
        ResultSet  executeQuery = createStatement.executeQuery("select id, value from example1");       
        while (executeQuery.next()) {               
            int id = executeQuery.getInt("id");
            System.out.println("id " + executeQuery.getString("id") + " value " + executeQuery.getString("value"));
            if (id == 3) {            
                deleteRow();
                Thread.sleep(5000);
                executeQuery.updateString("VALUE", "new value");
                executeQuery.updateRow();
            }
        }
        conn.close();
    }
    public static void deleteRow(){        
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    Connection conn = ConnectionDefinition.getOracleConnection();
                    PreparedStatement st = conn.prepareStatement("delete from example1 where id = 3");                    
                    st.execute();
                    st.close();
                } catch (Exception ex) {
                   ex.getStackTrace();
                }
            }
        };
        Thread  th = new Thread(r);
        th.start();
    }
}

要避免此类冲突,请在运行查询时使用Oracle FOR UPDATE功能。 ResultSet executeQuery = createStatement.executeQuery("select id, value from example1 for update");