2010-12-17 65 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