lastInsertId()获取的是该脚本插入的最后一个id还是整个数据库的最后一个id?

4

我想知道lastInsertId()是如何工作的。目前,我在使用它来获取插入行的id,以便在代码的其他部分中使用这个id。例如:

$stmt = $db->prepare('INSERT INTO image_table (image_name, image_size) VALUES (:image_name, :image_size)'); 

$stmt->execute(array(
    'image_name' => $photoName,
    'image_size' => $image_size / 1024, 
    ));

$lastInsertId = $db->lastInsertId('yourIdColumn');

好的,我要翻译的问题是:

1)这个脚本是否获取了在特定脚本中进行的SQL插入的lastInsertId

2)例如,假设3个不同的用户在几个纳秒的时间内将数据插入到同一张表中。会发生什么?

this script -> Inserts to row id 1
Another user -> Inserts to row id 2
Another user -> Inserts to row id 3

在这种情况下,lastInsertId()会返回值1,因为它是由该脚本插入的最后一行的id,而不是在执行lastInsertId()函数的那一行时的最后一个id,所以它不会返回3。

2
这是会话特定的。 - Strawberry
3
对于那个脚本/会话;否则它将相当无用。 - Mark Baker
顺便说一句,你可以打开两个窗口并自己测试一下... 或者你可以阅读文档: "生成的ID是在服务器上以每个连接为基础进行维护的。" 文档链接 - Bill Karwin
@BillKarwin 我试过了,但是没有起作用。当我把光标移动到另一个窗口提交第二个查询时,第一个脚本已经完成了。所以当我发布这个问题时,我不确定在实时环境中每个用户的插入之间仅有纳秒差异时它会如何工作。 :) - Neel
1
所以如果LAST_INSERT_ID()返回最后生成的id——即使它是60秒前生成的——为什么需要测试如此快速的时间?您可以在每个窗口中输入一个插入语句,然后在每个窗口中选择SELECT LAST_INSERT_ID()(它们将返回两个不同的数字),然后在窗口1中插入一行,并在窗口2中选择SELECT LAST_INSERT_ID(),以证明窗口2只能看到自己会话中生成的id。这个测试不需要精确的计时。 - Bill Karwin
显示剩余2条评论
1个回答

4
  1. 该脚本执行中 最后一次 sql 插入的 id(不是另一个用户进行的、与之竞争的插入)。

  2. 如果您有 3 次插入操作,它会返回如其所述的 lastInsertId(),即最后一次插入,而不是所有 3 次,也不是 2 次……只是最后一次。为了解决这个问题,可以分别运行插入操作并获取 id,或者根据插入条件进行搜索,需要再次提取数据时使用。 对于由不同的用户/会话进行的插入,请参见答案#1, lastInsertId() 适用于特定的用户/会话/执行,而不适用于所有操作。 同时,还会发生 MYSQL 数据库临时操作,如果那样的话,它们就会返回 id。

希望这可以帮到您。


1
1 正解,实际上也回答了2。2的答案不适用,因为问题是关于不同用户,而不是关于同一脚本中的三个语句。 - GolezTrol
抱歉,我误读成“如果我在一个表中插入了3个用户”(1个SQL查询),正确答案将会是什么。 - Jakub
2
我认为更好的答案是lastInsertId返回给定连接的最后插入的ID。在同一脚本中,我可以有许多个DB连接,每个连接插入不同的信息(甚至是对同一个DB的多个DB连接),并在每个连接上调用lastInsertId以获得不同的结果。在这种意义上使用术语“用户”有点模糊。术语“会话”更好,因为每个连接都有自己的会话。+1,虽然我认为你的答案已经表达了要点,但我的问题纯粹是语义问题。 - Jeff Lambert
借鉴@watcher的观点,user这个术语是错误的,特别是在数据库层面上,你的网站可能只有一个用户与数据库建立连接。 - Brian Warshaw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接