2010-12-17 60 views
6

我的表格有兩列:「id」(自動增量,主要)和「數字」(唯一)。現在我想要以下內容:MySQL - 如果存在,獲取主鍵。否則,添加條目

  • 如果號碼已經存在,則返回id;
  • else,向表中添加條目並返回其ID。

什麼是最有效的方法來完成這項工作?

注:

  • 有一個更大概率的數量是新的;
  • 該表將包含數十萬條記錄。

謝謝!

+1

我能想到的最佳方式是使用存儲過程,現在我無法提供示例,但請看一下 – 2010-12-17 23:51:49

回答

6
INSERT IGNORE INTO table (number) VALUES (42); 

SELECT id FROM table WHERE number = 42; 

這可能是MySQL中最高效的。您可以使用存儲過程將它們整理起來,這可能會也可能不會更有效。

編輯:

如果你認爲這將是罕見的新號碼上來,這將是更快:

SELECT id FROM table WHERE number = 42; 

if (!id) { 

    INSERT INTO table WHERE number = 42; 
    id = SELECT @LAST_INSERT_ID; 

} 

有一個可能的競爭條件在這裏如果併發線程同時選擇則同時插入相同的號碼。在這種情況下,後面的插入將失敗。您可以通過在此錯誤情況下重新選擇來恢復。

+0

我已更新我的問題。表格中會有數十萬條記錄,並且獲得新號碼的可能性會更大。存儲過程爲多條記錄創建多少差異? – Saad 2010-12-18 08:26:26

+0

在這種情況下,我會做插入,然後選擇,它更簡單,沒有競爭條件。假設你的數據庫服務器在你的Web服務器附近,存儲過程幾乎沒有什麼區別。您可以通過編寫兩個代碼路徑來輕鬆測試,然後對其進行壓力測試。 – Chris 2010-12-19 06:34:57

4

這裏是一個這樣的存儲功能,做你的描述:

CREATE FUNCTION `spNextNumber`(pNumber int) RETURNS int(11) 
BEGIN 
DECLARE returnValue int; 
SET returnValue := (SELECT Number FROM Tbl WHERE Number = pNumber LIMIT 1); 
IF returnValue IS NULL THEN 
    INSERT IGNORE INTO Tbl (Number) VALUES (pNumber); 
    SET returnValue := pNumber; -- LAST_INSERT_ID() can give you the real, surrogate key 
END IF; 
RETURN returnValue; 
END 
+0

使用方法如下: INSERT IGNORE INTO人物(數字)VALUES(pNumber); SET returnValue:=(SELECT Number FROM FROM WHERE Number = pNumber LIMIT 1); 我想這會更有效率? – Saad 2010-12-18 08:19:36

+0

它將取決於重複的頻率,正如克里斯在上面提到的那樣......嘗試不必要的插入和接觸IGNORE可能會比選擇...限制更昂貴1.然而,對於他關於比賽的觀點條件我在這個答案中插入了IGNORE。 – Tahbaza 2010-12-18 15:01:19

+0

感謝您的幫助Tahbaza!我已經修改了我的問題並添加了更多詳細信息,請問您能確認您的解決方案仍然是最好的還是您想修改它? – Saad 2010-12-18 18:26:20

1

我知道這是舊的,但它是一個普遍的問題。所以,爲了尋找解決方案的任何人,這裏有四種不同的方式來完成這個任務與性能基準測試。 http://mikefenwick.com/blog/insert-into-database-or-return-id-of-duplicate-row-in-mysql/

+2

雖然這個鏈接可能回答這個問題,但最好在這裏包含答案的基本部分,並提供參考鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 – 2012-09-27 14:36:26

+1

https://web.archive.org/web/20150915085727/http://mikefenwick.com:80/blog/insert-into-database-or-return-id-of-duplicate-row-in-mysql/ – dt192 2017-06-07 06:14:50