2015-09-05 80 views
0

當使用下面的代碼嘗試向數據庫表中插入新聞行時,我得到了完整性約束違規錯誤。SQLIntegrityConstraintViolationException由於重複鍵值

public void ExtractBoard() throws IOException, SQLException { 
    int rows = 0; 
    String sqlInser = "INSERT INTO APP.SUBSCRIBERBR (subID, boardno)"+"VALUES (?,?)"; 
    PreparedStatement stmt = conn.prepareStatement(sqlInser, Statement.RETURN_GENERATED_KEYS); 
    String[] AryFiles2 = rf.OpenFile(); 
    int i,j; 
    String p1 = "", p2 = ""; 
    for (i=0; i<AryFiles2.length; i++) { 
     if (AryFiles2[i].contains("ADD VSBR")) { 
      String[][] parts = this.LineParts(); 
      Scanner in = new Scanner(parts[i][0]).useDelimiter("[^0-9]+"); 
      int intst = in.nextInt(); 
      p1 = String.valueOf(intst); 
      for (j=0; j<parts[1].length; j++) { 
       if (parts[i][j].contains("MN")) { 
        Scanner inn = new Scanner(parts[i][j]).useDelimiter("[^0-9]+"); 
        int intstr = inn.nextInt(); 
        p2 = String.valueOf(intstr); 

       } 
      } 
     } 
     if(p1 != null && p2 != null){ 
      stmt.setString(1, p1); 
      stmt.setString(2,p2); 
      rows = stmt.executeUpdate(); 
     } 
     else { 
      throw new SQLException("Null parameters"); 
     } 
    } 
} 

這是我收到的錯誤消息。

java.sql.SQLIntegrityConstraintViolationException:語句被放棄,因爲它會造成一個獨特的或主鍵約束或通過在「SUBSCRIBERBR」定義「SQL150827011836400」標識的唯一索引中的重複的鍵值。

我該如何解決這個問題?

+0

這將是一個有點幫助,如果你可以發佈數據庫表的方案。但是,異常本身已經告訴你,你試圖將一個值作爲主鍵(或者至少是一個唯一的列)插入到數據庫中,該值已經存在。所以您還應該檢查您從中讀取值的文件的內容。 – sleepy42

回答

0

你的subID變量似乎是重複的。 (有一個在你的表相同的subID另一條記錄)

可能的原因是:

  1. 文件的閱讀方法是錯誤的,你最終會讀你的輸入文件是錯誤的。

  2. 您的輸入文件已包含重複鍵。

  3. 一切正常,但是您正試圖在不清洗的情況下針對同一數據庫運行您的代碼,因此您最終將從上次運行中找到具有此子ID的記錄。

+0

我認爲該文件有重複的鍵。我想獲得一些關於如何添加代碼行來跳過已插入的鍵的幫助,使用sql關鍵字'EXISTS'或其他。 – AAJ

+0

首先你應該驗證你的假設。 *然後*作爲一個可能的解決方案(因爲你正在尋找一些簡單的東西),我會建議簡單地捕獲SQLIntegrityConstraintViolationException並跳過違規行。 –

+0

詢問數據庫是否已寫入密鑰更容易(且比異常處理更便宜)。你可以使用一個簡單的選擇,比如'從APP.SUBSCRIBERBR中選擇subID,其中subID =?'。如果你沒有行,你可以插入。 –

0

你從未p1p2爲空,所以如果if聲明是在第一次迭代假的,你插入"", "",如果if語句是在隨後的迭代假的,你插入相同值如前面的迭代所做的那樣。

+0

如果他會插入值「」,「」他應該得到一個非空約束違規或類型違規,因爲'subID'是類型編號/ int的主鍵,我猜。 –

+0

@ dev.null你是對的,但也有這樣的情況,*那麼*這些代碼有很多錯誤,我甚至不會解決關於未顯示的事情的假設問題,比如列的數據類型,直到遠遠低於名單。相反,我選擇專注於保證重複錯誤的邏輯的一部分,這就是問題所在,而沒有對輸入數據的明確瞭解。 ---讓我們來看看....是的,可能會有一行或兩行代碼,我沒有問題。更多的是,如果你用末端大括號來統計線條。 – Andreas

0

我想你讀了錯誤的int,所以你最終得到錯誤的值並生成重複的鍵,這違反了約束條件。

你的主鍵來自parts[i][0](在0 i開始)在行:

Scanner in = new Scanner(parts[i][0]).useDelimiter("[^0-9]+"); 

但是,爲什麼你使用相同的值關於第二個SQL參數? p2設置爲parts[i][j]在行

Scanner inn = new Scanner(parts[i][j]).useDelimiter("[^0-9]+"); 

(記住:j從0開始,太)見行

for (j=0; j<parts[1].length; j++) { 

所以你讀parts[i][0]兩次。

第二個問題可能是for循環變量j的上限:您將其設置爲parts[1].length。不應該這部分[i] .length?

你怎麼解決它?看看你的價值p1p2,也許你可以登錄它。這些是你預期的價值嗎? 你有哪些限制?只有主鍵或boardno也有約束或唯一索引(請參閱錯誤消息)?

你可以嘗試這樣的事情:

try { 
    rows = stmt.executeUpdate(); 
} catch (Exception e) { 
    logger.error("p1="+p1+" p2="+p2+" catched="+e); 
} 
+0

我沒有讀取兩個sql參數的相同值。請注意,在if(parts [i] [j] .contains(「MN」))「 」之後有一個if語句 和 '我知道在我正在使用的文件中,包含字符串「MN」的部分從不在第一列(即部分[i] [0])中。 我在表中使用其他輸入文件正確的值。它只是這個文件給我的錯誤。 – AAJ

+0

你能告訴我們你的輸入文件的內容嗎? –

+0

對不起,我不能。 Compagny政策。 – AAJ