44

如果我使用执行单个记录插入的循环插入多条记录,则返回的最后一个插入 id 正如预期的那样是最后一个。但是如果我做一个多记录插入语句:

INSERT INTO people (name,age)
VALUES ('William',25), ('Bart',15), ('Mary',12);

假设上面的三个是表中插入的第一条记录。在插入语句之后,我希望最后一个插入 id 返回 3,但它返回 1。有问题的语句的第一个插入 id。

因此,有人可以确认这是否是LAST_INSERT_ID()多条记录 INSERT 语句上下文中的正常行为。所以我可以基于它来编写我的代码。

4

3 回答 3

47

是的。MySQL 文档last_insert_id()中记录了这种行为:

重要
如果您使用单个INSERT语句插入多行,LAST_INSERT_ID()则仅返回为第一个插入行生成的值。这样做的原因是可以轻松地INSERT针对其他服务器重现相同的语句。

于 2011-10-31T21:00:47.557 回答
2

MySQL的手册页中提到了这种行为。它在评论中,但没有受到挑战,所以我猜这是预期的行为。

于 2011-01-09T03:44:38.883 回答
2

我认为如果您的表具有唯一的自动增量列(ID)并且您不需要它们由 mysql 本身返回,这是可能的。我会花费你 3 个额外的数据库请求和一些处理。这将需要以下步骤:

  1. 在插入之前获取“在 MAX(ID) 之前”:
    SELECT MAX(id) AS before_max_id FROM table_name`
  1. 使用您的数据进行多个 INSERT ... VALUES () 查询并保留它们:

    INSERT INTO table_name
    (col1, col2)
    VALUES 
    ("value1-1" , "value1-2"), 
    ("value2-1" , "value2-2"), 
    ("value3-1" , "value3-2"), 
    ON DUPLICATE KEY UPDATE
    
  2. 在插入后立即获取“在 MAX(ID) 之后”:

    SELECT MAX(id) AS after_max_id FROM table_name`
    
  3. 获取 ID 介于“Before MAX(ID)”和“After MAX(ID)”之间的记录,包括:

    SELECT * FROM table_name WHERE id>$before_max_id AND id<=$after_max_id`
    
  4. 使用您插入的数据检查检索到的数据以匹配它们并删除任何不是您插入的记录。其余记录有您的 ID:

    foreach ($after_collection as $after_item) {
      foreach ($input_collection as $input_item) {
        if ( $after_item->compare_content($input_item) ) {
          $intersection_array[] = $after_item;
        }
      }
    }

这就是普通人在现实世界中使用部分代码解决问题的方式。多亏了自动增量,它应该得到尽可能少的记录来检查,所以它们不会需要大量的处理。这不是最终的“复制和粘贴”代码 - 例如。您必须根据需要创建自己的函数 compare_content()。

于 2018-09-21T14:16:23.220 回答