如何获取MySQL中最后更新的行的ID?


134

如何使用PHP获取MySQL中最后更新的行的ID?


2
mysqli_insert_id($ link)将完全返回最后更新的行的ID。我在项目中出于相同目的使用此功能。您可以在同步或异步查询中使用它。只需将$ lastupdated_row_id = mysqli_insert_id($ link)插入您的代码中,它将为您工作。
2013年

1
如果您进行更新,是否还不知道该行的ID?我猜肯定有些情况下您不这样做。
JCharette 2014年

1
您可能在更新查询中使用了where子句,为什么不能在select查询中使用相同的where子句?UPDATE foo WHERE bar = 1; SELECT id FROM foo WHERE bar = 1
Salman A

Answers:


236

我找到了这个问题的答案:)

SET @update_id := 0;
UPDATE some_table SET column_name = 'value', id = (SELECT @update_id := id)
WHERE some_other_column = 'blah' LIMIT 1; 
SELECT @update_id;

由aefxx 编辑

可以进一步扩展此技术以检索受更新语句影响的每一行的ID:

SET @uids := null;
UPDATE footable
   SET foo = 'bar'
 WHERE fooid > 5
   AND ( SELECT @uids := CONCAT_WS(',', fooid, @uids) );
SELECT @uids;

这将返回一个字符串,其中所有ID均由逗号连接。


6
不敢相信这有0个投票,而OP根本没有要求的mysql_insert_id()注释有13个。谢谢Pomyk,这是一个聪明的把戏!
JakaJančar2011年

1
由于您有一个WHERE子句,您可以WHERE在下一个查询中使用相同的子句SELECT id FROM footable WHERE fooid > 5
Salman

4
也许每个人都理解这一点,但是如果您使用mysql_query(); 您必须将其分为三个不同的调用,但是它将起作用。
rael_kid 2012年

8
甚至不需要使用变量。LAST_INSERT_ID()可以接受一个参数,该参数将设置下次调用时返回的值LAST_INSERT_ID()。例如:UPDATE table SET id=LAST_INSERT_ID(id), row='value' WHERE other_row='blah';。现在,SELECT LAST_INSERT_ID();将返回更新的ID。有关更多详细信息,请参见newtover的答案。
乔尔2014年

3
@SteveChilds我只是评论newtover的问题,并想为您描述的陷阱添加解决方案。如果没有什么可更新的,这会将LAST_INSERT_ID设置为0 UPDATE lastinsertid_test SET row='value' WHERE row='asd' AND LAST_INSERT_ID(id) OR LAST_INSERT_ID(0);。但是,它不会检索多个ID,因此此答案更好。
martinczerwi 2015年

33

嗯,令我惊讶的是,在答案中我没有看到最简单的解决方案。

假设item_iditems表中的一个整数标识列,并且使用以下语句更新行:

UPDATE items
SET qwe = 'qwe'
WHERE asd = 'asd';

然后,要知道该语句之后的最新受影响的行,应将语句稍作更新为以下内容:

UPDATE items
SET qwe = 'qwe',
    item_id=LAST_INSERT_ID(item_id)
WHERE asd = 'asd';
SELECT LAST_INSERT_ID();

如果您只需要更新真正更改的行,则需要通过LAST_INSERT_ID添加对item_id的条件更新,以检查行中的数据是否要更改。


3
这是多用户安全的,因为多个客户端可以发出UPDATE语句并使用SELECT语句(或mysql_insert_id())获得自己的序列值,而不会影响或受到生成自己序列值的其他客户端的影响。按照dev.mysql.com/doc/refman/5.0/en/...
brutuscat

1
这不会将item_id设置为最后插入的记录吗?
arleslie

2
@arleslie,如果您单击上面brutuscat的注释中文档的链接,您将不会看到它。这正是针对这种情况的预期行为。
newtover

1
这确实是正确的答案。尽管查询似乎有点违反直觉,但这确实是MySQL文档所说的。
Timothy Zorn 2014年

3
万一查询使您感到困惑,因为LAST_INSERT_ID(expr)将为UPDATE调用返回expr的值,您也可以像这样使用它:UPDATE items SET qwe = 'qwe' WHERE asd = 'asd' AND LAST_INSERT_ID(item_id); SELECT LAST_INSERT_ID();
martinczerwi 2015年

14

官方上这很简单,但明显违反直觉。如果您正在做:

update users set status = 'processing' where status = 'pending'
limit 1

更改为此:

update users set status = 'processing' where status = 'pending'
and last_insert_id(user_id) 
limit 1

的添加last_insert_id(user_id)where子句告诉MySQL来设置它的内部变量为所找到的行的ID。当您传递一个last_insert_id(expr)类似的值时,它最终会返回该值,对于像此处这样的ID来说,它始终是一个正整数,因此始终求值为true,而不会干扰where子句。这仅在实际找到某行的情况下才有效,因此请记住检查受影响的行。然后,您可以通过多种方式获取ID。

的MySQL last_insert_id()

您可以生成序列而无需调用LAST_INSERT_ID(),但是以这种方式使用该函数的实用工具是将ID值作为最后一个自动生成的值保留在服务器中。这是多用户安全的,因为多个客户端可以发出UPDATE语句并使用SELECT语句(或mysql_insert_id())获得自己的序列值,而不会影响或受到生成自己序列值的其他客户端的影响。

的MySQL mysql_insert_id()

返回由先前的INSERT或UPDATE语句为AUTO_INCREMENT列生成的值。对包含AUTO_INCREMENT字段的表执行INSERT语句,或者使用INSERT或UPDATE设置带有LAST_INSERT_ID(expr)的列值后,请使用此功能。

LAST_INSERT_ID()和mysql_insert_id()之间存在差异的原因是,使得LAST_INSERT_ID()易于在脚本中使用,而mysql_insert_id()试图提供有关AUTO_INCREMENT列发生了什么的更准确的信息。

的PHP mysqli_insert_id()

使用LAST_INSERT_ID()函数执行INSERT或UPDATE语句还将修改mysqli_insert_id()函数返回的值。

放在一起:

$affected_rows = DB::getAffectedRows("
    update users set status = 'processing' 
    where status = 'pending' and last_insert_id(user_id) 
    limit 1"
);
if ($affected_rows) {
    $user_id = DB::getInsertId();
}

(仅供参考,DB类在这里。)


需要注意的重要一点:这是多连接安全的,last_insert_id或mysql_insert_id(也许还有mysqli_insert_id,我没有检查)的持久值是按连接的。太棒了!
瑞安S

10

这与Salman A的答案相同,但是这是您实际需要执行的代码。

首先,编辑您的表,以便它可以自动跟踪每当修改行时。如果只想知道最初插入行的时间,请删除最后一行。

ALTER TABLE mytable
ADD lastmodified TIMESTAMP 
    DEFAULT CURRENT_TIMESTAMP 
    ON UPDATE CURRENT_TIMESTAMP;

然后,要查找最后更新的行,可以使用此代码。

SELECT id FROM mytable ORDER BY lastmodified DESC LIMIT 1;

这段代码都是从MySQL相对于PostgreSQL删除的:在表MySQL手册:对行进行排序中添加了“最后修改的时间”列。我刚刚组装好了。


7
如果在第一次插入查询之后立即进行了第二次插入,则此方法可能会获取错误的ID。但是,如果我们在此查询中使用“ WHERE”,即从mytable ORDER BY lastmodified DESC LIMIT 1 WHERE中选择SELECT ID(某些条件与上次插入查询有关),则可能会阻止获取错误的ID。
Naeem Ul Wahhab,2013年

1
@ TheNoble-Coder这是事实。如果需要获取影响特定更新查询的行的ID,请使用Pomyk的技术。当异步使用(您只需要绝对的最后更新)时,此处的此技术会更有用。
乍得冯瑙

5

查询:

$sqlQuery = "UPDATE 
            update_table 
        SET 
            set_name = 'value' 
        WHERE 
            where_name = 'name'
        LIMIT 1;";

PHP功能:

function updateAndGetId($sqlQuery)
{
    mysql_query(str_replace("SET", "SET id = LAST_INSERT_ID(id),", $sqlQuery));
    return mysql_insert_id();
}

这对我有用;)


我喜欢相同但跑不同的ref:forums.mysql.com/read.php?52,390616,390619

3

进一步了解上述公认的答案
对于那些想知道:==

:=和之间的显着区别=是,它:=在所有地方都可以用作变量赋值运算符,而=仅在SET语句中可以那样工作,而在其他地方则是比较运算符。

因此SELECT @var = 1 + 1;@var保持不变并返回布尔值(1或0取决于@var的当前值),而SELECT @var := 1 + 1;将其更改@var2返回2 [资源]


嘿,谢谢。他们的意思实际上比上面接受的答案更有趣。
格林

2

嘿,我只需要一个技巧-我以另一种方式解决了它,也许对您有用。请注意,这不是可扩展的解决方案,对于大型数据集将非常不利。

将查询分为两部分-

首先,选择要更新的行的ID,并将其存储在临时表中。

其次,使用update语句中的条件更改为进行原始更新where id in temp_table

为了确保并发性,您需要在这两个步骤之前锁定表,然后在最后释放锁。

再次,这对我有效,对于以结尾的查询limit 1,所以我什至不使用临时表,而只是使用一个变量来存储first的结果select

我更喜欢这种方法,因为我知道我将总是只更新一行,并且代码很简单。


2
SET @uids := "";
UPDATE myf___ingtable
   SET id = id
   WHERE id < 5
  AND ( SELECT @uids := CONCAT_WS(',', CAST(id AS CHAR CHARACTER SET utf8), @uids) );
SELECT @uids;

我必须CAST id(不知道为什么)...或者我无法获取@uids内容(这是一个斑点),顺便说一句,感谢Pomyk的回答!


2

最后更新的行的ID与您在“ updateQuery”中用于发现和更新该行的ID相同。因此,无论如何,只要保存(调用)该ID即可。

last_insert_id()取决于AUTO_INCREMENT,但最后更新的ID不取决于。


3
如果更新不是通过id而是通过另一组属性来完成,该怎么办?
塞巴2014年

2

我的解决方案是,首先使用select命令确定“ id”(@ uids),然后使用@uids更新此id。

SET @uids := (SELECT id FROM table WHERE some = 0 LIMIT 1);
UPDATE table SET col = 1 WHERE id = @uids;SELECT @uids;

它对我的项目有效。


1

如果您只进行插入操作,并且希望在同一会话中进行插入操作,请按照peirix的回答进行操作。如果要进行修改,则需要修改数据库架构以存储最近更新的条目。

如果您想要上次修改的ID(可能是来自其他会话的ID)(即不是当前运行的PHP代码刚刚完成的ID,而是为了响应不同的请求而完成的ID),则可以添加一个表的TIMESTAMP列称为last_modified(请参见http://dev.mysql.com/doc/refman/5.1/en/datetime.html有关信息,),然后在更新时设置last_modified = CURRENT_TIME。

设置好之后,您可以使用以下查询:SELECT ID FROM table ORDER BY last_modified DESC LIMIT 1; 获取最新修改的行。


-9

不需要那么长的Mysql代码。在PHP中,查询应如下所示:

$updateQuery = mysql_query("UPDATE table_name SET row='value' WHERE id='$id'") or die ('Error');
$lastUpdatedId = mysql_insert_id();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.