2010-02-08 119 views
30

我有一個包含3列的表 - id(pk),pageId(fk),name。我有一個php腳本,它將大約5000條記錄轉儲到表中,其中大約一半是重複的,具有相同的pageId和名稱。 pageId和名稱的組合應該是唯一的。當我在php中循環腳本時,防止重複項保存到表中的最佳方法是什麼?避免重複進入mysql數據庫的最佳方法

回答

96

第一步是設置一個唯一的鑰匙放在桌子上:

ALTER TABLE thetable ADD UNIQUE INDEX(pageid, name); 

然後,你必須決定你想要做什麼時,有一個重複。你應該:

  1. 忽略它嗎?

    INSERT IGNORE INTO thetable (pageid, name) VALUES (1, "foo"), (1, "foo"); 
    
  2. 覆蓋之前輸入的記錄?

    INSERT INTO thetable (pageid, name, somefield) 
    VALUES (1, "foo", "first") 
    ON DUPLICATE KEY UPDATE (somefield = 'first') 
    
    INSERT INTO thetable (pageid, name, somefield) 
    VALUES (1, "foo", "second") 
    ON DUPLICATE KEY UPDATE (somefield = 'second') 
    
  3. 更新計數器?

    INSERT INTO thetable (pageid, name) 
    VALUES (1, "foo"), (1, "foo") 
    ON DUPLICATE KEY UPDATE (pagecount = pagecount + 1) 
    
+3

BIG謝謝,這是我在Stack Overlow上研究了一段時間的問題的絕佳答案。 – capfu 2011-10-25 06:29:12

1

您可以將PageID和Name設置爲MySQL數據庫中的唯一索引。這樣插入行時,會導致一個錯誤,PHP可以忽略這個錯誤,您可以直接進入下一行。

這裏假定您要單獨插入行。又名:

foreach($large_data as $fields) 
{ 
    mysql_query("INSERT INTO TABLE (`Something`) VALUES('".$fields['something']."'); 
} 
+1

有意允許的mysql_query()拋出PHP警告,當你打重複行是那種凌亂(它雜波您的日誌,它的資源相對密集的,等等)。特別是在首先防止它們就像使用其他解決方案中提到的MySQL的'INSERT IGNORE'功能一樣簡單。另外,在批量插入語法可用時,插入循環效率不高。 – 2010-02-08 06:58:13

1

從MySQL點,你可以做

alter table YOURTABLE add unique index(pageId, name); 

如果你的寫法是正確的,你想從PHP這樣做,你可以做

$already_done = array(); 
foreach ($records as $record) 
{ 
    $unique_hash = md5($record['name'].$record['pageId']); 
    if (!in_array($unique_hash, $already_done)) 
    { 
     $already_done[] = $unique_hash; 
     // sql insert here 
    } 
} 

無論哪種方式,這些應你沒事吧。

+1

當然,如果在腳本啓​​動之前*表中已經有記錄,那麼這些記錄就不會出現在'$ already_done'中。 – 2010-02-08 07:00:28

3

您也可以忽略mysql的錯誤:INSERT IGNORE INTO TABLE ...它會忽略關鍵錯誤,跳過該插入並轉到下一個。