2014-02-25 35 views
3

我在AS400系統的LIBRARY1.TRACKINGTABLE上有一個跟蹤表。此表有5個領域:(EX 123456789)(EX 20131202)。SQL INSERT:指定重複鍵值?

  1. SSN 9,0非空
  2. DATE 8,0非空
  3. TIME 6,0(如133000 )非空
  4. PRINT_NEW Z(EX。2013-12-02-11.23.47.965000)(使用CURRENT_TIMESTAMP)非空
  5. PRINT_OLD Z(EX。2013-12-02-11.23.47.965000)(CURRENT_TIMESTAMP使用)NULLABLE

在我的申請中,在處理過程中,如果用戶希望將處理後的文檔提交到圖像文件服務器,我會提示用戶。如果在對話框中單擊「是」,則所有已處理的文檔將從C:中的本地文件夾移至共享網絡文件夾。

然後我有一個包含在處理文檔中的所有SSN的數組。對於SSN的陣列中的每個人,我稱之爲叫updateAddrChangHistory(ssn)功能,更新我的跟蹤表:

  // PROMPT USER TO COMMIT 
      DialogResult dResult = MessageBox.Show("Mail Merge Completed. Individual Documents Saved to C:\\TEMP\\to fyi\\. \n\n Commit generated documents to NetFYI?", "Confirm Commit", MessageBoxButtons.YesNo); 
      if (dResult == DialogResult.Yes) 
      { 
       moveLocalToCommitFYI(); 

       // If selected letter is New/Old Address Letter, and thus tracked in table LIBRARY.TRACKINGTABLE, 
       // update the tracking table using SSN's stored in SSNsArray. 
       if (cmbLetterType.SelectedIndex < 2) 
       { 
        // Now that user has "theoretically" printed and Commited the processed documents, update Change History Table 
        foreach (string ssn in SSNsArray) 
        { 
         if (ssn != null && ssn.Length > 0) 
         { 
          updateAddrChngHistory(ssn); 
         } 
        } 
       } 
       SSNsArray = new string[0]; // Clear the array for next processing 
       updatePrintedCntLabel(); 
      } 

然後根據其處理的文檔類型,我要麼插入新記錄(表示一個新的地址字母已被打印)或UPDATE記錄(表示舊地址字母已被打印爲同一成員)。

public void updateAddrChngHistory(string SSN) 
    { 
     // Update/Modify Tracking Table 
     string formattedDate = dtpDate.Value.ToString("yyyyMMdd"); 
     //string formattedTime = DateTime.Now.TimeOfDay.ToString("HHmmss"); 
     string query = ""; 
     switch (docType) 
     { 
      case "oldAddr": 
       query = "UPDATE LIBRARY.TRACKINGTABLE SET PRINT_OLD = CURRENT_TIMESTAMP WHERE SSN = " + SSN + " AND PRINT_OLD IS NULL"; 
       break; 
      case "newAddr": 
       query = "INSERT INTO LIBRARY.TRACKINGTABLE (SSN, DATE, TIME, PRINT_NEW, PRINT_OLD) VALUES (" + SSN + ", " + formattedDate + ", " + System.DateTime.Now.ToString("HHmmss") + ", CURRENT_TIMESTAMP, NULL)"; 
       break; 
      case "nameChg": 

       break; 

      case "nameChgWAR": 

       break; 
     } 

     mdl.InsertUpdateData(query); 
     // Close Connection 
     mdl.closeConn(); 
    } 

mdl.InsertUpdateDate()是一個類文件中的函數:

namespace MergeDoc 
{ 
    public class MergeDocClassLibrary 
    { 
     OdbcConnection conn = new OdbcConnection(); 

     public void InsertUpdateData(string query) 
     { 
      // PROD 
      string connString = "DRIVER=Client Access ODBC Driver (32-bit); SYSTEM=XX.XX.X.XX; UID=XYXYXYZ; PWD=YXZYXZY"; 
      // DEV 
      //string connString = "" 

      OdbcCommand cmd = new OdbcCommand(query, conn); 

      // Set connection using connectionString 
      conn.ConnectionString = connString; 
      // Open Connection 
      conn.Open(); 
      // Execute command and store in OBDC DataReader 
      cmd.ExecuteReader(); 
     } 
    } 
} 

我的問題是以下

我的最終用戶在虛擬機上。當他們運行應用程序時,我們假設處理97個新的地址信件記錄,72個將記錄到跟蹤表中。每一次,在處理一些問題時,他們收到以下錯誤(文檔之後成功地移動到圖片服務器處理文件夾):

Duplicate Key Error

盡我所知,這是從我的INSERT語句而產生。然而,我無法弄清楚的是,爲什麼有幾條記錄成功地將其放入表格中,然後突然之間出現這種錯誤。更令人沮喪的是,我似乎無法在我自己的機器上覆制錯誤(即使清除跟蹤表並處理與我的用戶相同的記錄)。

有沒有其他人有這個錯誤的經驗?有什麼想法來解決這個問題?

SSN是已處理的SSN,DATE是從我的應用程序datepicker控件中選擇的日期,TIME是當前系統時間,而print new是當前日期時間。這四個字段都是非NULL值,應該共同創建一個完全獨特的值。

+0

是'SSN'你是主鍵? –

+0

我正在檢查。一個數據庫管理員創建了這個表格,而且我不熟悉如何檢查AS400表格。我在VS2012中建立了連接。 –

回答

3

此代碼有很多問題

應該測試公開賽之前打開的連接。

你爲什麼要打開連接?

你可以使用一些錯誤捕捉
你會知道錯誤是存在的,應該能夠得到更多的細節

你不應該用一個的ExecuteReader()用於更新或插入
更新或插入應該是的ExecuteNonQuery()

基於更新和插入語句最有可能的SSN是PK
顯示您正在執行插入doctype是否newAddr與如果SSN不存在檢查。

if(string.IsNullOrEmpty(query)) return; 
try 
{ 
    OdbcCommand cmd = new OdbcCommand(query, conn); 
    conn.ConnectionString = connString; 
    conn.Open(); 
    cmd.ExecuteReader(); 
} 
catch (OdbcException Ex) 
{ 
    Debug.WriteLine(Ex.Message); 
    throw Ex; 
} 
finally 
{ } 
+0

我有一些錯誤檢查,秋天回來在我的代碼的大部分。連接實際上是通過對同一個類的不同過程調用而關閉的。對不起,我試圖只包含相關的代碼來解決這個問題。 –

+0

在不同的程序中打開和關閉不是一種好的代碼實踐。至少應該測試一個開放的連接。 – Paparazzi

+0

「盡我所知,這是源於我的INSERT語句。」這就是爲什麼你在那裏測試異常。 – Paparazzi

2

這是一個更清晰的消息SQL問題。您不能使用與現有行相同的SSN添加新行。現有的行可能已經存在了10年,或者它可能是在拋出異常之前添加的行。

switch()可能會將您向下發送一個令人困惑的路徑。無論某個外部進程聲明「舊」或「新」地址,此代碼都需要更新現有的行並添加不存在的行。想象一下這種情況。外部進程看到SSN 123進來。它檢查文件並且123不在那裏。所以它將交易標記爲「新」。然後,5個文件稍後處理另一個傳入的SSN 123文件。外部進程檢查文件,123不在那裏,因此它將該事務標記爲「新」。當你開始調用updateAddrChngHistory時,SSN 123的第一個實例會被正確插入,但之後有5個文檔,SSN 123的下一個實例是重複的,並且INSERT失敗。這只是這種情況發生的一種方式。

如果你不想陷的重複鍵異常,你需要在你的SQL來測試它:

INSERT INTO LIBRARY.TRACKINGTABLE 
    (SSN, DATE, TIME, PRINT_NEW, PRINT_OLD) 
    VALUES (" + SSN + ", " + formattedDate + ", " + 
     System.DateTime.Now.ToString("HHmmss") + ", CURRENT_TIMESTAMP, NULL) 
    where ssn not in (select ssn from library.trackingtable) 
+0

感謝您的簡潔解釋巴克。經過進一步審查,看起來像SSN,日期和時間都是表中的關鍵字段。另一個問題是,我插入系統日期和系統時間,當我應該已經插入日誌/時間存儲在更改日誌我查詢每個記錄返回在我的查詢要處理的文檔。 Datec/Timec中的不匹配我認爲導致了我遇到的幾個問題。如果這確實是解決方案,會報告回來! –