我有以下查询:
INSERT INTO table (a) VALUES (0)
ON DUPLICATE KEY UPDATE a=1
我想要插入或更新的ID。通常我会运行第二个查询以获取此信息,因为我认为insert_id()只返回'inserted'ID而不是更新的ID。
有没有办法INSERT / UPDATE并检索行的ID而不运行两个查询?
答案 0 :(得分:149)
查看此页:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
在页面的底部,他们解释了如何通过将表达式传递给MySQL函数来使LAST_INSERT_ID对更新有意义。
从MySQL文档示例:
如果表包含AUTO_INCREMENT列并且INSERT ... UPDATE插入行,则LAST_INSERT_ID()函数返回AUTO_INCREMENT值。如果语句更新了一行,则LAST_INSERT_ID()没有意义。但是,您可以使用LAST_INSERT_ID(expr)解决此问题。假设id是AUTO_INCREMENT列。要使LAST_INSERT_ID()对更新有意义,请按如下方式插入行:
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), c=3;
答案 1 :(得分:31)
确切地说,如果这是原始查询:
INSERT INTO table (a) VALUES (0)
ON DUPLICATE KEY UPDATE a=1
和'id'是自动增量主键,而不是工作解决方案:
INSERT INTO table (a) VALUES (0)
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), a=1
全部在这里:http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
如果表包含AUTO_INCREMENT列并且INSERT ... UPDATE 插入一行,LAST_INSERT_ID()函数返回 AUTO_INCREMENT值。如果语句更新了一行, LAST_INSERT_ID()没有意义。但是,你可以解决这个问题 通过使用LAST_INSERT_ID(expr)。假设id是AUTO_INCREMENT 列。
答案 2 :(得分:2)
您可以查看REPLACE,如果记录存在,则基本上是删除/插入。但这会改变自动增量字段(如果存在),这可能会破坏与其他数据的关系。
答案 3 :(得分:2)
我不知道你的MySQL版本是什么,但是对于InnoDB,有autoinc的错误
5.1.20中的错误,并在5.1.23中更正 http://bugs.mysql.com/bug.php?id=27405
5.1.31中的错误,并在5.1.33中进行了更正 http://bugs.mysql.com/bug.php?id=42714
答案 4 :(得分:0)
值得注意的是,这可能是显而易见的(但为了清楚起见,我会说清楚),REPLACE会在插入新数据之前吹掉现有的匹配行。 ON DUPLICATE KEY UPDATE仅更新您指定的列并保留该行。
来自manual:
REPLACE与INSERT完全一样, 除非表中有一个旧行 与a的新行具有相同的值 PRIMARY KEY或UNIQUE索引,旧的 在新行之前删除行 插入
答案 5 :(得分:0)
如果您使用自动增量,现有解决方案仍然有效。我有一种情况,用户可以定义一个前缀,它应该在3000重新启动序列。由于这个不同的前缀,我不能使用自动增量,这使得插入时last_insert_id为空。我解决了以下问题:
INSERT INTO seq_table (prefix, id) VALUES ('$user_prefix', LAST_INSERT_ID(3000)) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id + 1);
SELECT LAST_INSERT_ID();
如果前缀存在,它将递增它并填充last_insert_id。 如果前缀不存在,它将插入值为3000的前缀,并使用3000填充last_insert_id。
答案 6 :(得分:0)
我遇到了一个问题,当ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID(id)将主键增加1时,会话中下一个输入的id将增加2