【问题标题】:PDO - lastInsertId() for insert query with multiple rowsPDO - lastInsertId() 用于插入多行查询
【发布时间】:2012-09-16 11:35:32
【问题描述】:

我可以将 2 个宠物插入一个表中,并获取它们的 lastInsertId() 以一次进一步处理一个(2 个查询)。
我想知道如果我在 1 个查询中插入 2 行,是否有办法获取两个 lastInsertIds() 并将它们分配给变量:

$query = "INSERT INTO pets (pet_name) VALUES (':coco'),(':jojo')";
$pet_insert = $dbh->prepare($query);
$pet_insert->execute(array(':coco' => $coco,':jojo' => $jojo));
$New_PetID = $dbh->lastInsertId();

是否可以获取 coco 和 jojo 的 lastInsertId() ?所以像:

$New_PetID1 = $dbh->lastInsertId();//coco
$New_PetID2 = $dbh->lastInsertId();//jojo

这将给出相同的 ID,有什么方法可以得到这 2 个 ID?仅供参考,这是在 try 块中。

【问题讨论】:

    标签: mysql pdo last-insert-id


    【解决方案1】:

    我在第一条语句中使用了数组,在第二条语句中添加了if condition。所以如果插入记录得到它的最后一个 id 然后做第二个语句。如果插入第二个数组得到它的最后一个 id 然后重复第二个语句

        for ($count=0; $count < count($_POST["laptop_ram_capacity"]); $count++) { 
            $stmt = $con->prepare('INSERT INTO `ram` 
                    (ram_capacity_id, ram_type_id, ram_bus_id, ram_brand_id, ram_module_id)
                    VALUES (?,?,?,?,?)');
    
                //excute query//
                $stmt->execute(array(
                                $_POST['laptop_ram_capacity'][$count],
                                $_POST["laptop_ram_type"][$count],
                                $_POST["laptop_ram_bus"][$count],
                                $_POST["laptop_ram_brand"][$count],
                                $_POST["laptop_ram_module"][$count]
                                ));
                //fetsh the data//
                $rows = $stmt->rowCount();
                // i add the below statment in if condition to repeat the insert and pass the repeated of the last statement//
                if ($rows > 0) {
                $LASTRAM_ID = $con->lastInsertId();
    
                $stmt = $con->prepare('INSERT INTO `ram_devicedesc_rel` 
                    (ram_id, Parent_device_description_id)
                    VALUES (?,?)');
    
                //excute query//
                $stmt->execute(array(
                                $LASTRAM_ID,
                                $LASTdevicedesc_ID
                                ));
                //fetsh the data//
                } else {
                    echo "Error: " . $sql . "<br>" . $conn->error;
                }                                    
            }
    

    【讨论】:

      【解决方案2】:

      好吧,由于 1000 次插入比 1 次插入有点长,所以话题的问题仍然很有趣。可能的解决方法是进行 2 次查询。第一个是插入 1000 行,第二个是如果在这些插入的行中有独特的东西,则选择它们。 以宠物为例:

      INSERT INTO pets ( name ) VALUES ( 'coco', 'jojo' );
      SELECT id FROM pets WHERE name IN ( 'coco', 'jojo' );
      

      这只会对大数据集带来好处。

      【讨论】:

      • (你会想要SELECT name, id FROM ...,这样你就可以确定它们是如何匹配的。)(我的经验表明,批次中超过 100 行的任何东西的速度大约是每次 1 行的 10 倍。时间。)
      【解决方案3】:

      您可以将 1 添加到最后插入 id 以获得真正的最后一条记录 id。如果您插入超过 2 条记录,只需将 rowCount - 1 添加到 last_insert_id。

      将 innodb_autoinc_lock_mode 设置为 0(“traditional”)或 1(“consecutive”),任何给定语句生成的自动增量值将是连续的,没有间隙,因为表级 AUTO-INC 锁一直保持到语句的结尾,并且一次只能执行一个这样的语句。

      生成的 ID 在每个连接的基础上在服务器中维护。这意味着函数返回给给定客户端的值是为影响该客户端的 AUTO_INCREMENT 列的最新语句生成的第一个 AUTO_INCREMENT 值。此值不受其他客户端的影响,即使它们生成自己的 AUTO_INCREMENT 值。此行为可确保每个客户端都可以检索自己的 ID,而无需担心其他客户端的活动,也无需锁定或事务。

      欲了解更多信息,请阅读此文档http://dev.mysql.com/doc/refman/5.1/en/innodb-auto-increment-handling.html

      【讨论】:

      • 这就是答案,阅读文章即可。为什么是负点?
      • 如承诺 - 我会在 24 小时内将赏金放在这里(100,而不是 50,因为 50 不可用)(所以现在不允许我这样做)
      • @zerkms 我不建议使用这种方法。尝试插入:INSERT INTO test_table` (id, name) VALUES (null, 'Example'), (15, 'Example'), (null, 'Example');` 此代码不适用于此案例。
      • @IStranger ...确实,当显式插入 auto_increment Id 时,代码将不起作用。但是,如果您让 mysql 管理 auto_increment id,这种方法可以正常工作。
      【解决方案4】:

      你可以使用'multi_query()' 将所有查询添加到一个变量中,例如: '$sql1 = "第一次插入";' '$sql2 = "第二次插入";' '$sql3 = "第三次插入";'等等... 计算您要制作的插入数量。 现在使用 'multi_query()' 执行所有的 '$sql' 查询。 获取最后一个插入 id。 现在你所要做的就是'$rowno = $lastinsertid - $countofinserts'。 所以基本上你会得到一个数字。 向它添加 1,从结果数字到 lastinsertid 是您运行的插入查询的插入 ID

      【讨论】:

      • 不要使用multi_query;它具有安全隐患。
      【解决方案5】:

      我试图假设这是不可能的,直到我自己尝试并认为这是可能的

      每次执行后,添加 lastInsertId() 并分配一个键。

      以我为例:

      // First query
      $sql = "INSERT INTO users
      (username, email)
      values
      (:username, :email)";
      $sth = $this->db->prepare($sql);
      $sth->bindParam(':username', $data['username'], PDO::PARAM_STR);
      $sth->bindParam(':email', $data['email'], PDO::PARAM_STR);
      
      // Second Query
      $sql2 = "INSERT INTO users
      (username, email)
      values
      (:username, :email)";
      $sth2 = $this->db->prepare($sql2);
      $sth2->bindParam(':username', $data['username'], PDO::PARAM_STR);
      $sth2->bindParam(':email', $data['email'], PDO::PARAM_STR);
      
      // Start trans
      $this->db->beginTransaction();
      
      // Execute the two queries
      $sth->execute();
      $last['ux1'] = $this->db->lastInsertId(); // <---- FIRST KEY
      
      $sth2->execute();
      $last['ux2'] = $this->db->lastInsertId(); // <---- SECOND KEY
      
      // Commit
      $this->db->commit();
      

      我能够检索最后插入的两个 ID

      数组 ( [创建] => 数组 ( [ux1] => 117 [ux2] => 118 )

      )

      我希望这会帮助其他正在寻求正确答案的人。

      【讨论】:

      • 您有 2 个准备好的语句,OP 只有一个,只有一个带有批量插入的查询。所以没有错,只是和OP有的不匹配。
      • 如果不是两个查询而是 100 个查询,性能会怎样?
      【解决方案6】:

      请,请避免布鲁斯给出的解决方案类型。自动增量值可以设置为不同于 1。例如在主到主复制的情况下。不久前,运行我们的一个应用程序的主机更改了它们的数据库设置。我碰巧注意到 - 纯粹是巧合 - 突然间,id 增加了 2 而不是 1。我们会不会有这样的代码,它可能会给我们带来严重的问题。

      【讨论】:

        【解决方案7】:

        有可能!您需要做的就是调用 PDO lastInsertId() 方法。这将在执行多个或批量 INSERT 时返回第一个插入的 id。接下来我们需要对受最后一个 INSERT 语句影响的行数进行简单的加减运算。

        $firstInsertedId = $this->lastInsertId();
        $InsertedIds = range($firstInsertedId, ($firstInsertedId + ($stmt->rowCount() - 1)) );
        print_r($InsertedIds);
        

        【讨论】:

        • 我不建议对其进行数学计算。最好的方法是每次插入都做。
        • @RickJames 我不建议使用这种方法。尝试插入: INSERT INTO test_table (id, name) VALUES (null, 'Example'), (15, 'Example'), (null, 'Example');此代码不适用于这种情况。
        【解决方案8】:

        documentation 声明:Returns the ID of the last inserted row or sequence value

        您需要执行两个查询来获取每个插入行的 id。

        【讨论】:

          【解决方案9】:

          这是不可能的。如果您需要为两行生成 id - 您需要执行 2 个单独的 INSERT

          重要如果您使用单个 INSERT 语句插入多行, LAST_INSERT_ID() 返回为 第一次插入生成的值 仅行。这样做的原因是为了让重现成为可能 很容易对其他服务器执行相同的 INSERT 语句。

          http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_last-insert-id

          【讨论】:

          • 有可能获取 last_insert id 并添加插入的行数 (-1) 以获得真正的 last id,不是吗?
          • @Peymanabdollahy 不是,不是。您不能保证在您插入第一行和第二行之间没有插入任何内容。
          • 你读过这篇文章吗? dev.mysql.com/doc/refman/5.1/en/…
          • @Peymanabdollahy 你有什么特别要说的吗?如果有,请明确地说出来。我没时间玩你的游戏,抱歉。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2019-10-04
          • 2013-11-06
          • 2010-11-13
          • 2012-04-21
          相关资源
          最近更新 更多