如何在MySQL中更新现有记录以获得新的自动增量ID?

时间:2014-05-28 09:39:39

标签: mysql auto-increment

我有一个主键表(其名称为" id")定义为auto_increment。我在INSERT语句中使用NULL来"填充" id值。当然,它有效。但是现在我需要"移动"现有记录到新的主键值(下一个可用,值不是那么重要,但它必须是新的,如果按id排序则是最后一个)。我怎么能在一个优雅的"办法?因为"在INSERT"处使用NULL使用UPDATE不起作用太多:

update idtest set id=NULL where id=1;

这只会使记录的id为零。我希望与INSERT做同样的事情,但似乎我的想法不正确。

当然我可以使用" INSERT ... SELECT"语句,然后旧的DELETE,或者我可以使用像MAX(id)+ 1这样的东西在一步中更新旧记录的ID等,但我很好奇是否有更好的解决方案。

此外,MAX(id)解决方案似乎无法正常工作:

mysql> update idtest set id=max(id)+1 where id=3;
ERROR 1111 (HY000): Invalid use of group function
mysql> update idtest set id=(select max(id)+1 from idtest) where id=3;
ERROR 1093 (HY000): You can't specify target table 'idtest' for update in FROM clause

3 个答案:

答案 0 :(得分:3)

这是我相信的方式:

UPDATE users SET id = (SELECT `AUTO_INCREMENT`
FROM  INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND   TABLE_NAME   = 'users') WHERE id = 2;

select * from users;

我用自己的表替代你的。

test是数据库名称,在我的情况下,users是表名,idAUTO_INCREMENT

编辑:上面的我的查询工作完美,但其副作用有些“危险”,下次插入时AUTO_INCREMENT值将与最近更新的记录发生冲突,因此下一次插入将失败。为了避免这种情况,我将上述查询修改为了一个事务:

START transaction;

    UPDATE users SET id = (SELECT `AUTO_INCREMENT`
        FROM  INFORMATION_SCHEMA.TABLES
        WHERE TABLE_SCHEMA = 'test'
        AND   TABLE_NAME   = 'users') WHERE id = 2;

    #renew auto increment to avoid duplicate warning on next insert
    INSERT IGNORE INTO users(username) values ('');

COMMIT

希望如果不是OP,这将有助于某人。

答案 1 :(得分:2)

您尝试更新同一个表的方式有误,但您可以在同一个表上使用连接

update idtest t
join (select id +1 as id
    from idtest order by id desc 
    limit 1) t1
set t.id=t1.id
where t.id=3;

update idtest t
join (select max(id) +1 as id
    from idtest ) t1
set t.id=t1.id
where t.id=3;

答案 2 :(得分:1)

您可以使用REPLACE INTO子句来执行此操作。

从手册:

REPLACE的工作原理与INSERT完全相同,只是如果表中的旧行与PRIMARY KEY或UNIQUE索引的新行具有相同的值,则在插入新行之前删除旧行。请参见第13.2.5节“INSERT语法”。

修改 我的错误(在评论中)你必须有两个独特的约束才能实现这个目标:

当你使用auto_increment值来替换记录时,记录将被替换为给定ID并且不会改变(但是AI值会增加)。

您必须从查询中排除AI列。如果你还有一个UQ约束,你可以这样做。

检查此SQLFiddle演示:http://sqlfiddle.com/#!2/1a702e

第一个查询将替换所有记录(但id的值不会更改)。 第二个也将替换它,并将使用新的AI值。 (请注意,第二个查询不包含id列,并且some列上存在UQ约束。

您可以注意到,第二个查询使用的AI值高于排除的值:这是因为第一个替换增加了AI值。

如果没有两个唯一键(一个用于AI,另一个用于另一列),则REPLACE语句将作为普通的INSERT语句使用!

(当然,您可以使用PRIMARY KEY更改其中一个UNIQUE KEY)