ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)而不增加自动索引

时间:2016-11-09 21:12:20

标签: mysql sql duplicates

我正在运行SQL查询,看起来有点像这样

INSERT INTO people (Name, Role)
VALUES('{$Name}', '{$Occupation')
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id)

'人民' table有一个代理ID密钥作为主密钥,由MySQLs Autoindex设置。

'名称'和'角色'被组合成一个复合的唯一键。

问题是,当我运行此查询并命中具有相同名称和角色的人并获取其各自的ID时,自动索引仍会增加。

是否可以轻松地防止这种情况,或者我是否需要运行2个单独的查询来检查是否已存在然后插入?

2 个答案:

答案 0 :(得分:2)

首先,如果自动增量增加,您不必担心。不可否认,这在美学上是丑陋的,但序列中的差距并不重要。而且,差距可能出于其他原因。

但是,如果这很重要,您可以通过查询查询来降低发生这种情况的可能性:

INSERT INTO people (Name, Role)
    SELECT name, role
    FROM (SELECT '{$Name}' as name, '{$Occupation}' as role) x
    WHERE NOT EXISTS (SELECT 1 FROM people p WHERE p.name = x.name)
    ON DUPLICATE KEY UPDATE name = VALUES(name);  -- no op;

你仍然可以获得可能出现差距的竞争条件,但这样做的可能性要小得多。

答案 1 :(得分:1)

正如insert ... on duplicate key update上的mysql文档所说:

  

例如,如果列a声明为UNIQUE并包含该值   1,以下两个陈述具有类似的效果:

INSERT INTO table (a,b,c) VALUES (1,2,3)   ON DUPLICATE KEY UPDATE
c=c+1;

UPDATE table SET c=c+1 WHERE a=1; 
     

(效果不一样   一个InnoDB表,其中a是一个自动增量列。与   自动递增列,INSERT语句增加   自动递增值,但UPDATE不会。)

因此,对于innodb表,这是预期的行为。您可以为表选择不同的表引擎,或者如果您不希望在更新时增加自动增量字段,则不能使用on duplicate key update子句。注意:auto_increment id的序列中有间隙没有错。如果业务要求是连续递增的序列号,那么您不应该使用自动增量。

更新

如果你担心很快就会耗尽bigint范围,那么使用uuid() mysql函数或类似的东西来为你生成唯一的id。但是无符号bigint的最大范围非常大......