2012-04-27 315 views
0

我试图从Excel文件插入一些数据到表中。我有两个excel文件如下:Oracle:唯一约束违反了异常,但我的数据实际上并未违反它

Test2: 
5/12/2012  5/18/2012 ABQ ANC 1 52 
5/12/2012  5/18/2012 ABQ ANC 2 30 
5/12/2012  5/18/2012 ABQ ANC 3 34 
5/12/2012  5/18/2012 ABQ ANC 4 41 
5/12/2012  5/18/2012 ABQ ANC 5 53--->duplicate row 
5/12/2012  5/18/2012 ABQ ANC 6 18 
5/12/2012  5/18/2012 ABQ ANC 7 4 
5/12/2012  5/18/2012 ABQ ATL 1 389 
5/12/2012  5/18/2012 ABQ ATL 2 312 

测试1:

5/12/2012  5/18/2012 ABQ ATL 4 259 
5/12/2012  5/18/2012 ABQ ATL 5 362 
5/12/2012  5/18/2012 ABQ ATL 6 240 
5/12/2012  5/18/2012 ABQ ATL 7 88 
5/12/2012  5/18/2012 ABQ ANC 5 53--->duplicate row 
5/12/2012  5/18/2012 ABQ AUS 2 2 
5/12/2012  5/18/2012 ABQ BDL 1 164 
5/12/2012  5/18/2012 ABQ BDL 2 128 
5/12/2012  5/18/2012 ABQ BDL 3 132 

我的表,下手就是空的。所以我插入第一个文件(test2),它工作正常。当插入第二个文件(test1)时,它应该在test1的第5行给出“违反唯一约束”异常。我为了测试而复制了那一行。我写了下面的代码来做插入。正如可以看到的批量大小为3

当插入第二文件,该代码执行第一批次(其是第一3行)的罚款。在第二批(第4-6行)中,因为行(5)中的一个被复制,所以会引发BatchUpdatException。我捕捉到这个异常,并且在catch块中,我每次处理一行(第4-6行)。所以行4插入应该工作正常。但事实并非如此。它会抛出一个sqlException。第5行也抛出异常(重复行)。但第6行不。第6行executeUpdate()运行良好。在这一点上,如果我看看我的数据库表,我发现第4行也与第6行一起插入到表中。怎么会发生这种情况,它只是在第4行抛出一个异常?

我的目标是让用户知道哪里有重复的行。由于这种异常行为,用户被告知当他们尝试插入第二个文件时,行4和行5中存在重复行。

String sqlStatement = "INSERT INTO DMD_VOL_UPLOAD (ORIGIN, DESTINATION, DAY_OF_WEEK, EFFECTIVE_DATE, DISCONTINUE_DATE, VOLUME)"; 
    int batchSize=3; 
    sqlStatement += " VALUES(?, ?, ?, ?, ?, ?)"; 
    con = session.connection(); 
     pstmt = con.prepareStatement(sqlStatement); 
    for(currentRow=1; currentRow<=rowCount; currentRow++){ 
     try{ 
       forecastBatch = (ForecastBatch) list.get(currentRow-1);         
       pstmt = (PreparedStatement) prepareStatement(pstmt, forecastBatch);   
       pstmt.addBatch();    
       if(currentRow % batchSize == 0 || currentRow==rowCount){ 
        updateCounts = pstmt.executeBatch(); 
        con.commit(); 
        pstmt.clearBatch(); 
       }       
     }catch(BatchUpdateException e){ 
       int endPoint = currentRow; 
       int i; 
       for(i=currentRow-batchSize; i<endPoint; i++){ 
        forecastBatch = (ForecastBatch) list.get(i); 
        try{ 
         pstmt = (PreparedStatement) prepareStatement(pstmt, forecastBatch); 
         pstmt.executeUpdate();**strong text** 
         con.commit(); 
        }catch(SQLException ex){ 
         errorRowNum = errorRowNum + (i+1) + ", "; 
         ex.printStackTrace(); 
        } 
       } 
     }catch(SQLException e){ 
       e.printStackTrace(); 
     } 
    }//end of the first for loop 
+0

试图单独插入行之前,您尝试在批量插入失败后执行显式回滚吗? – 2012-04-27 20:33:05

+0

不,我没有试过 – Susie 2012-04-27 20:43:45

+0

@ Eric Petroelje就是这样,我不得不明确地回滚。非常感谢你。 Amaazzing ... – Susie 2012-04-27 21:25:34

回答

1

当你executeBatch一个批处理语句,一些语句可能会成功,有些语句可能会失败。如果一条语句失败,那并不意味着JDBC驱动程序回滚成功的语句。如果一个语句失败,JDBC驱动程序可能会选择尝试执行批处理中的所有语句,或者一旦语句失败,它可能会选择停止执行批处理语句(这听起来像您使用的驱动程序选择将执行语句停止为一旦出现故障)。

当你得到一个BatchUpdateException,你需要调用getUpdateCounts。这会给你的int数组,告诉你要么声明多少行更新,一个Statement.SUCCESS_NO_INFO指示语句成功,但没有行数是可用的,或表明该声明失败Statement.EXECUTE_FAILED。我希望你会得到一个两个元素的数组,指示批处理中的第一条语句(电子表格中的第4行)成功,批处理中的第二条语句(电子表格中的第5行)失败。数组中缺少第三个元素将表示批处理中的第三条语句(电子表格中的第6行)未被执行。您的重试代码需要仅重试未执行的语句。在这种情况下,只有第三条语句(电子表格中的第6行)需要重试,因为BatchUpdateException已经告诉您第一条语句成功,第二条语句失败。

+0

是的,我的驱动程序遇到故障时会停止执行。如果我的批处理大小为3,并且批处理中的第二条语句失败,那么也会导致前面的语句失败。因此,当我调用getUpdatecounts()时,我得到了3个元素的数组,所有3个元素的值都是EXECUTE_FAILED。现在的问题是,找出批处理中的哪个语句抛出异常。因此,我不知道从哪里开始重试。 – Susie 2012-04-27 20:58:24

+0

@javaStudent - 这没有意义。如果你得到3个元素的数组,这意味着驱动程序试图执行批处理中的所有三个语句。如果数组的所有三个元素都是'Statement.EXECUTE_FAILED',那意味着所有三个语句都失败了。这不符合你描述的其他行为。您使用的是什么JDBC驱动程序? – 2012-04-27 21:05:03

+0

我正在使用oracle 11g。我不确定那会是什么车手。我很抱歉,我在这方面比较新。我所做的只是当我得到batchUpdateException时,我查看了updatecounts的值,它们都是EXECUTE_FAILED。因此,在我的catch块中,我尝试一次处理所有3个语句。有没有一种方法可以找出我正在使用的jdbc驱动程序。 – Susie 2012-04-27 21:15:08