2013-03-04 53 views
0

所以,我有一個僱員表如下:檢查重複根據兩列

empid | companyid | empnum | ... 
    1 |  1  | 1 | ... 
    2 |  1  | 2 | ... 
    3 |  1  | 3 | ... 
    4 |  2  | 1 | ... 
    5 |  2  | 2 | ... 

上表中的每個員工入職獲得一個唯一的ID(EMPID)由MSSQL自動生成。我有一個PHP應用程序,它將一個CSV文件作爲員工的「主列表」輸入。但是,該CSV文件只有來自右側的「empnum」的列(它不包含companyid或明顯的employeeid)。我遍歷CSV文件的每一行時都會添加companyid。 CSV 只包含不在數據庫中的員工,但沒有保證,所以我需要檢查以確保員工在插入前不在那裏。驗證方法是確保對於這個特定的companyid(假設我們爲companyid = 1插入),表中沒有匹配的empnum。所以,如果我有這個數據的CSV文件,這將是有效的:

empnum, ... 
4, ... 

但是,如果我有一個CSV與此數據文件,它不會是有效的:

empnum, ... 
3, ... 

由於3已經作爲companyid = 1的empnum存在,ENTIRE導入應該失敗。在PHP應用程序,我有:

try { 
    db->beginTransaction(); 
    while (($data = fgetcsv($handle, 5000, ",")) !== FALSE) { 
     //SQL TO INSERT ROW 
    } 
    db->commit(); 
} catch (PDO Exception) { 
    db->rollBack(); 
} 

我應該使用什麼SQL插入行,以便它會導致異常如果empnum已經存在該companyid?我需要做什麼數據庫更改?我最初的想法是:

選項1 - 插入到一個臨時表中,然後運行一個select查詢,該查詢在companyid/empnum中的匹配值上連接兩個表,如果它返回大於0的行,則拋出異常。 PRO:只有一個選擇。 CON:所有內容都被插入到臨時表中如果它通過select select =很多浪費時間,則轉儲到臨時表中

選項2-根據當前行執行select語句,如果它返回行> 0,拋出異常,否則插入真正的表。 PRO:你一旦遇到失敗就會發現失敗,這樣你就可以節省自己的時間。 CON:你的查詢現在增加了(2x-1),所以如果你成功的話,你會有很多額外的開銷!

所以我的問題是: - 什麼是最好的選擇(1,2,或別的東西完全)? - 我可以以某種方式讓MSSQL在插入時拋出異常嗎?

+0

這不是確切的代碼,但你可以得到一個想法: $ nextEmpnum =( 「SELECT MAX empnum FROM employee_table WHERE companyid =」 $ COMPANY_ID)+1 「INSERT INTO employee_table值(」 $ nextEmpnum。 「,」。$ company_id – 2013-03-05 00:00:07

+0

對不起,我應該指定更好的,我沒有試圖爲empnum創建一個唯一的id,empnum將由導入數據的公司提供,我只需要看看員工已經在桌子上存在(基於companyid和empnum的組合) – 2013-03-05 00:43:55

+0

另外,不知道爲什麼這個問題得到了downvote。如果你downvoted,請說明原因! – 2013-03-05 04:15:09

回答

1

選項1是加載數據的「標準」方式(當然在我的世界中)。您的臨時表實際上稱爲「臨時」表。這比逐行檢查要快得多(查找RBAR)。

其實什麼將始終以最時間做事逐行。

一個mudmap性能對比:

選項1:

  1. 做你的初始插入到錶行由行(慢)表之間
  2. 捕獲重複同一個SELECT查詢(快)
  3. 如果成功的,複製到舉辦現場表(快速)

選項2:

  1. 載入你的數據從您的CSV行由行(中)
  2. 雖然這樣做,捕獲,通過每次選擇複製逐行(慢)

什麼並不清楚是什麼做的當你在選項2中找到重複項時,你會這樣做嗎?你想要回滾所有其他記錄還是要通知用戶並繼續?

+0

在這個時候,我有3個「屏幕」他們走過。首先是選擇文件並上傳它。其次通過閱讀CSV顯示所有數據的預覽。他們打進口,然後我的問題生效。更多地考慮這一點,也許在預覽期間,我可以以某種方式標記任何顯示爲重複的東西並阻止它們導入? – 2013-03-05 01:39:51

+1

對我來說,這會增加一個臨時表的權重,因爲在將它加載到最終表之前,需要「暫存」它。你可以使用INSERT INTO FinalTable SELECT * FROM StaginTable WHERE Status ='Import'將它傳輸到最終表中。只要知道你爲用戶增加了複雜性,他們並不總是那樣!上傳的文件如何進入數據庫 - 是批量加載還是您有一些PHP代碼逐行插入並插入?有多少條記錄? – 2013-03-05 03:34:30

+1

登臺表的另一個原因是當某人在數字字段或格式不正確的日期有txt時。您可以只用文本字段將所有內容加載到臨時表中,並添加此數據清理過程。否則,如果您只是嘗試將CS​​V數據直接加載到您的目標中,則可能會出現數據轉換問題以及重複問題。 – 2013-03-05 03:36:15