2013-05-02 68 views
6

我有一個MySQL查詢,看起來像這樣:避免唯一鍵的重複中插入查詢

INSERT INTO beer(name, type, alcohol_by_volume, description, image_url) VALUES('{$name}', {$type}, '{$alcohol_by_volume}', '{$description}', '{$image_url}')

唯一的問題是,名字是一個獨特的價值,如果我碰上重複,這意味着,我得到一個錯誤這樣的:

Error storing beer data: Duplicate entry 'Hocus Pocus' for key 2 

有沒有一種方法,以確保SQL查詢不會嘗試添加已經存在,而無需運行SELECT查詢整個數據庫獨特的價值?

+1

+1清晰並易於理解您的問題 – bestprogrammerintheworld 2013-05-02 13:26:36

+0

如果唯一值已經存在,您希望發生什麼?覆蓋現有的數據?或者改變_name_來自動產生一些獨特的東西? – 2013-05-02 16:41:52

回答

8

當然你使用INSERT的可以忽視INTO,像這樣:

INSERT IGNORE INTO beer(name, type, alcohol_by_volume, description, image_url) VALUES('{$name}', {$type}, '{$alcohol_by_volume}', '{$description}', '{$image_url}') 

你可以使用ON DUPLICATE KEY爲好,但如果你只是不想添加行INSERT IGNORE INTO是一個更好的選擇。 ON DUPLICATE KEY更適合,如果您想在重複時做更具體的事情。

如果您決定使用ON DUPLICATE KEY - 請避免在具有多個唯一索引的表上使用此子句。如果你有多個唯一索引ON DUPLICATE KEY -clause可以給人意想不到的結果的表(你真的沒有100%的控制權發生了什麼事情發生)

例子: - 這行下面只更新一行(如果類型爲1和alcohol_by_volume 1(和兩列是唯一索引))

ON DUPLICATE KEY UPDATE beer SET type=3 WHERE type=1 or alcohol_by_volume=1 

概括起來:

ON DUPLICATE KEY少了點沒有警告或錯誤時有重複的工作。

INSERT IGNORE INTO當有重複時會拋出警告,但除此之外,只是忽略將重複項插入到數據庫中。

0

是的,首先從數據庫中選擇名稱,如果查詢結果不爲空(零記錄),那麼名稱已經存在,並且您必須獲得另一個名稱。

+1

唯一的問題是如果在SELECT和INSERT之間的時間段插入記錄 – 2013-05-02 12:57:39

+0

然後,「ON DUPLICATE」可能有幫助,如果可行的話,現有的行更新當然... – Borniet 2013-05-02 12:59:47

6

正因爲如此,MySQL中有一種方法是使用ON DUPLICATE KEY UPDATE。這是因爲現有的MySQL 4.1

INSERT INTO beer(name, type, alcohol_by_volume, description, image_url) 
    VALUES('{$name}', {$type}, '{$alcohol_by_volume}', '{$description}', 
    '{$image_url}') 
    ON DUPLICATE KEY UPDATE type=type; 

你也可以使用INSERT IGNORE INTO...作爲替代,但聲明仍拋出一個警告(雖然,而不是錯誤)。

2

是的,有。您可以使用mysql INSERT語句的ON DUPLICATE KEY子句。語法解釋here

INSERT INTO beer(name, type, alcohol_by_volume, ...) 
    VALUES('{$name}', {$type}, '{$alcohol_by_volume}', ...) 
    ON DUPLICATE KEY UPDATE 
    type={$type}, alcohol_by_volume = '{$alcohol_by_volume}', ... ; 
1

非常簡單 - 您的代碼需要找出它想要做什麼,如果有東西試圖插入重複的名稱。因此,你首先需要做的是運行一個select語句:

SELECT * FROM beer WHERE name='{$name}' 

,然後運行「如果」語句關閉的,要確定是否有一個結果。

如果結果= 0,那麼繼續並運行插入。 否則......無論你想做什麼。拋出一個錯誤給用戶?以不同的方式修改數據庫?完全忽略它?這個插入語句是如何產生的?來自文件的批量更新?用戶從網頁輸入?

您到達此插入語句的方式以及它如何影響您的工作流程,應該確切地確定您如何處理「其他」。但是你一定要處理它。

但是隻要確保select和insert語句一起在一個事務中,以便其他人進來做同樣的東西不是問題。

+0

問題是如果OP可以在不使用select語句的情況下進行插入和檢查。 – bestprogrammerintheworld 2013-05-02 13:32:01

+0

是的,但沒有其他解決方案給出反饋。該計劃的反饋意見非常重要...並且對於整體情況所涉及的細節很少,我認爲強調這一點非常重要。 – 2013-05-02 15:10:30

+0

「其他解決方案沒有提供反饋」您是什麼意思?你說程序的反饋很重要。當然 - 如果有必要的話。但是,當可以使用數據庫引擎時,應該使用它。我的意思是 - 當有函數來處理這樣的情況,並且在MySQL中有一個函數來處理它時,爲什麼不使用它們呢?就我所見,沒有任何理由。 – bestprogrammerintheworld 2013-05-02 18:32:12