2014-01-10 49 views
2

在我的數據庫的表具有以下列:ID,CAMPAIGN_ID,opt_out_day 其插入一組「選擇退出天」的方法 - DATETIME值的陣列 - 如下:如何在執行MySQL INSERT時防止列對的值重複?

/** 
* @param Integer $campaignId 
* @param Array $optOutDays Array of DATETIME values 
*/ 
public function addCampaignOptOutDays($campaignId, $optOutDays) { 
     $query = "INSERT INTO `".self::$tblOptOutDays."` 
        (campaign_id, opt_out_day) 
        VALUES 
        (:campaign_id, :opt_out_day)"; 

     try { 
      $this->connection->beginTransaction(); 
      $query = $this->connection->prepare($query); 
      $query->bindParam(':campaign_id', $campaignId, \PDO::PARAM_INT); 
      foreach ($optOutDays as $day) { 
       $query->bindParam(':opt_out_day', $day, \PDO::PARAM_STR); 
       $query->execute(); 
      } 
      $this->connection->commit(); 
     } catch (\PDOException $e) { 
      $this->connection->rollback(); 
      throw new \Models\Database\DatabaseException($e->getMessage()); 
     } 
    } 

如何修改查詢以防止爲廣告系列重複選擇同一日期?換句話說,只要他們具有不同的'campaign-id',就可以在此表中存在具有相同opt-out-day的多行。 儘管爲(campaign_id,opt_out_day)添加一個唯一關鍵字並不是一個選項,因爲我不想在這種情況發生時拋出異常,我只是不想再次添加對。

+1

您可以使用'INSERT IGNORE',以便MySQL在遇到重複時不會拋出錯誤。你應該有獨特的指標,因爲不管錯誤的價值會在哪一天滑落。 –

回答

2

嘗試使用INSERT ... ON DUPLICATE KEY更新ID = ID

http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

這將避免額外的SELECT查詢但如果您有重複的密鑰,也會避免錯誤。

有也INSERT IGNORE ...但可能忽略其他錯誤以及

+1

如果您使用INSERT ... ON DUPLICATE KEY UPDATE,您將需要檢查受影響的行值。對於插入,它將是1,或者對於更新將是2。在「ON UPDATE」部分中,將列值設置爲相同的值,並且更新將被跳過。 –

+0

感謝Markus我已經更新了答案,以反映您給出的更詳細擴展的一部分。 –

+0

他沒有唯一的索引 –

-1

我不是用php的familiair,但如果你從表中選擇並檢查是否返回一個值,如果沒有,然後插入?

嘗試

$checkquery = "SELECT 1 FROM `".self::$tblOptOutDays."` 
WHERE campaign_id=:campaign_id AND opt_out_day=:opt_out_day)"; 

然後

IF $checkquery <> 1 THEN 
// run insert 
+0

這會產生併發問題,這意味着你可能會得到重複。 –

+0

不,它不會?它檢查你想插入的組合值是否存在'(campign_id AND opt_out_date)',如果它檢查到checkquery將返回空,這意味着if檢查是真實的並且會發生插入。 –

+0

如果兩個人同時運行SELECT查詢,則兩個SELECT都將不返回結果,並且兩個會話都可以插入相同的值。如果你能想到一個場景,上述情況會有效,請解釋一下。順便說一句,我不是那個倒票的人。 –

0

由於雅庫布·卡尼亞評論,你可以使用一個唯一索引並使用INSERT IGNORE

隨着置之不理,該行仍沒有插入,但沒有發生錯誤。 忽略的錯誤可能會生成警告,但重複鍵 錯誤不會。

然後,只需檢查受影響的行值以查看插入是否成功。

因此,其他錯誤仍然可以作爲警告檢測到。我認爲INSERT ... ON DUPLICATE KEY UPDATE是一個更好的解決方案,因爲添加唯一索引是因爲檢查警告可能是一個痛苦。

+0

」儘管爲(campaign_id,opt_out_day)添加一個唯一的密鑰並不是一個選項,因爲我不想在這種情況發生時拋出異常,我只是不想再添加一對。「 –

+0

@KayNelson,'INSERT IGNORE'不會拋出異常。 –

+0

不,但您需要一個唯一的索引才能運行INSERT IGNORE。否則,它只是插入它,你會得到重複。 –