检索多行的最后插入id

23

在向具有自增主键的表中插入数据时,我需要获取该键以便在另一个语句中使用。许多问题在SO上都显示可以使用mysql_insert_id()在PHP中完成此操作。

然而,我已经将我的插入分组在一起,所以一次插入了多行。我这样做是因为我猜想可能会出现一些性能问题,请告诉我如果我错了。但是,据我所知,mysql_insert_id()仅返回最后一个id,而我需要所有插入行的ids。

我想在这种情况下我可以:

  1. 使用一些简单的数学方法来计算使用mysql_insert_id()和我输入的行数的所有ids。但是这是否保证始终正确?

  2. 为每一行使用多个插入语句

  3. 在使用自增之前生成我的ID。

我相信这一定是一个经典的问题,所以我想知道最常见和最可取的方法是什么。


在必要时,可以向表中添加新列,并插入GUID,根据GUID可以轻松获取所有记录。 - garish
2个回答

34

调用last_insert_id()将返回最后一批次中插入的第一个行的ID。所有其他插入的行都保证是连续的。

除非你在做一些非常奇怪的事情,否则这样可以很容易地计算出每一行的ID。

实际上,根据innodb自增模式参数的设置,5.1中的行为会有所不同;但这应该无关紧要。只要你不将其从默认值更改,就会看到预期的行为。

有时候这种方式不会按照你的期望进行,也不是特别有用 - 例如,如果你使用ON DUPLICATE KEY UPDATE或INSERT IGNORE。在这些情况下,你需要做一些其他的工作来确定每一行的ID。

但对于普通的INSERT批处理,没有为自动增量列指定值,这很容易。

这里提供了有关innodb如何处理自动增量的完整描述。


1
我假设使用InnoDB,因为大多数应用程序都应该使用InnoDB,它是最好的通用引擎。 - MarkR
是的,但你的数学会有问题,因为last_insert_id()给出的是第一个ID,而不是最后一个。Chaos是正确的,因为它并不绝对保证是连续的,请阅读上面的链接。 - MarkR
所以你必须先锁定表格吗?还是使用事务? - user317033
你不需要锁定表格或使用显式事务。请参阅文档。你只需要确保自增模式未设置为非默认值2。innodb_auto_inc_lock_mode=2 可能会破坏许多应用程序。 - MarkR
如何使用“插入忽略批处理”?如果第一个是重复的,它会返回最后一个ID为0还是第二个插入的ID。如何将那些未被插入的映射到已插入的记录? - Friso Kluitenberg
显示剩余3条评论

2

如果我是你,我会采用以下几种方法:

首先,使用默认值为CURRENT_TIMESTAMPCreateDate字段。您可以选择CURRENT_TIMESTAMP以获取日期,插入运行,然后使用select id from table where CreateDate > $mytimestamp进行查询。

其次,您可以在表上创建一个触发器,在插入后记录并将新ID放入一个小型审计表中。在检查这些ID之前,请清空该表。如果您的表有数百万行,我建议使用此方法。


“CURRENT_TIMESTAMP” 这种方法对我来说有点危险。如果你和其他人同时在同一张表上写入(相同的时间戳),会发生什么? - tonix

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