Php 如何知道在重复键更新查询之后是否更新或插入了行

Php 如何知道在重复键更新查询之后是否更新或插入了行,php,mysql,pdo,Php,Mysql,Pdo,我需要插入到表中或更新值 我需要知道数据是更新的还是新创建的 目前我的逻辑是选择,如果不存在插入,如果存在更新 我需要计算更新的行数和插入的行数 这很慢,我需要一种更快的方法:我可以使用INSERT或REPLACE而不首先尝试选择,并让PDO客户端返回行是更新了还是插入了 我正在使用PHP/PDO/MySQL 使用伪代码更新: 当前逻辑: <?php $rowExists = PDO SELECT by key if ($rowExists) PDO UPDATE by key

我需要插入到表中或更新值

我需要知道数据是更新的还是新创建的

目前我的逻辑是选择,如果不存在插入,如果存在更新

我需要计算更新的行数和插入的行数

这很慢,我需要一种更快的方法:我可以使用INSERT或REPLACE而不首先尝试选择,并让PDO客户端返回行是更新了还是插入了

我正在使用PHP/PDO/MySQL

使用伪代码更新:

当前逻辑:

<?php
$rowExists = PDO SELECT by key

if ($rowExists)
    PDO UPDATE by key
    $updates++
else
    PDO INSERT
    $inserts++
通缉逻辑:

<?php
PDO INSERT .. ON DUPLICATE KEY
$updates++ or $inserts++ according to what it actually did

如果在重复密钥更新中使用,则可以剪切一步选择。因此,这将只是一个查询

以下是文件:

至于检查,代码如下:

if($stmt->rowCount() > 0 ){
    if($stmt->lastInsertId() != 0){
        echo 'Row was inserted';
    }else{
        echo 'Row was updated';
    }
}else{
    echo 'row was neither updated or inserted';
}

如果表有主键或唯一索引,则需要替换为。

如果表有主键或唯一索引,则需要替换为

假设您有一个id列为主键a和b的表,并且有一条记录1,2,3。id=1有了新的值,即a=4和b=5,但不想检查id=1是否已经存在条目

INSERT (id, a, b) VALUES (1, 4, 5) ON DUPLICATE KEY UPDATE a = VALUES(a), b = VALUES(b);
将在找到主键后更新。

如果您愿意,我正在使用MariaDB或MySQL,并且正在寻找此问题的解决方案,因此我看到了这篇文章。它部分地回答了这个问题,但没有完全解决我想要达到的目标。我从德国Danfrom读到的问题是:在我的一个或多个事务中,有多少记录被添加到数据库中,有多少记录被更新到数据库中

因此,利用本文中的一些有用元素,我提出了以下解决方案: 在我的实际代码中,我将其全部包装在try/catch中,并假设$dbx是一个实例化的PDO mysql数据库对象

/* 
    Get the current table row count 
      (it's our starting point, so any inserted row will increase the count)
*/

    $stmt = $dbx->query("SELECT COUNT(*) FROM `destination_table`");
    $row = $stmt->fetch(PDO::FETCH_NUM);
    $startCount = $row[0];
    $stmt = null;

/* 
    Set an iteration counter
     (
      I was using a prepared statement looping through
      INSERT / ON DUPLICATE KEY UPDATE, so want to check each loop for any change
     )
*/

    $countAnAction = 0;

/* 
  Prepare the INSERT with ON DUPLICATE KEY UPDATE for each line to process
   (assuming `a` is the key, regardless of type)
*/
    $stmt = $dbx->prepare("
       INSERT INTO `destination_table` (`a`,`b`)
       VALUES(:a, :b1) 
       ON DUPLICATE KEY UPDATE `b` = :b2
      ");
    $stmt->bindParam('a', $a, PDO::PARAM_STR);
    $stmt->bindParam('b1', $b, PDO::PARAM_STR);
    $stmt->bindParam('b2', $b, PDO::PARAM_STR); # set update value if a exists
// Assume we have an associative array of 'a', 'b' values passed to process
    foreach($inputRowToProcess as $arrVals)
    {
      # Set our prepared values from the array elements
        $a = $arrVals['a'];
        $b = $arrVals['b'];
        $stmt->execute();
      /* Now check if something happened and increment $countAnAction
        (
         $stmt->rowCount() on MySQL can be 1 or 2, depending on the action
         based off a value greater than zero, update the row count by 1
        )
      */
        if($stmt->rowCount() > 0)
        {
            $countAnAction += 1;
        }
    }

    $stmt = null;

// Now we get the count of rows in the destination table after the process has finished
    $stmt = $dbx->query("SELECT COUNT(*) FROM `destination_table`");
    $row = $stmt->fetch(PDO::FETCH_NUM);
    $endCount = $row[0];
    $stmt = null;

// Finally apply some math to the various elements to determine inserted count and updated count
                $insertedRows = $endCount - $startCount;
                $updatedRows = ($endCount - $startCount) + $countAnAction;

有插入。。。关于重复密钥update@MarcB我知道,但它能告诉我是更新了还是插入了吗?请使用伪代码查看我的更新问题。如果插入了该问题,则最后一个插入id将具有该新行的新id。但这只适用于一次插入。如果您使用的是扩展插入语法或插入。。。从中选择,然后所有赌注都被取消。@YourCommonSense很好,现在您将问题指向一些旧的mysql答案。。。。。非常有用..我如何知道它是否真的插入或更新了?@DanFromGermany检查$stmt->lastInsertId,如果没有插入任何内容,例如$stmt->lastInsertId>0inserted':'updated'@DanFromGermany see my Update这只适用于自动递增键,当我在插入前有PK时它就不起作用了:/什么不起作用?请你解释一下,你在这里犯了一个非常常见的错误,假设这个站点总是只有一个用户。但是,很显然,情况不会如此。因此,任何并发进程都可能完全破坏您的数学。此外,如果密钥存在并且执行了更新,$stmt->rowCount=1,则您的这种假设是完全错误的。感谢您的常识,您认识到了上述rowCount假设的缺陷,并已恢复正确。此外,表锁定似乎解决了我添加行的特定“用例”中的数学问题。我没有在我的工作中加入这些台词。在这里发帖还是新鲜事,所以我也应该更新一些东西吗?我认为这一点都不重要,因为目标可以通过一个简单的条件实现,如链接的答案所示。而桌面锁定是一个非常危险的游戏,应该避免