2012-04-27 313 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