ON DUPLICATE KEY查询-提取表的主键

时间:2019-04-23 18:41:13

标签: php mysql pdo

我有一个查询,我想将某些数据INSERT放入表中,如果特定字段checkPoint中已经有数据,请运行UPDATE。经过大量研究后,用户建议使用ON DUPLICATE KEY。

该查询可用于更新已存在的行,它插入一个具有新主键的新行,请有人可以解释我哪里出了问题或我错过了什么。

<?php
      $idUsers = $_SESSION['id'];
      $ModuleID = 5;
      $checkPoint = 999;

      $query= "INSERT INTO `userTakingModule` (`userTakingModuleID`, `idUsers`, `ModuleID`, `checkPoint`) VALUES (NULL, $idUsers, $ModuleID, $checkPoint) ON DUPLICATE KEY UPDATE `idUsers` = VALUES ($idUsers), `ModuleID` = VALUES ($ModuleID), `checkPoint` = VALUES ($checkPoint) "; 

      $result = $conn -> query($query);
?>

我的数据库布局的屏幕截图:中间名为userTakingModule的表是查询所应用的地方。

<code>checkPoint</code> Screenshot

这就是目前正在发生的事情,因为我需要以某种方式将userTakingModuleID的主键包含到查询中。 (我几乎要说,要查找哪里有idUserModuleID相同的条目?)

Table Screenshot

1 个答案:

答案 0 :(得分:2)

使用INSERT...ON DUPLICATE KEY UPDATE的重要部分是告诉MySQL密钥是什么,以便它可以查找重复项。你说:

  

我几乎要说一遍,寻找哪里有idUserModuleID相同的条目

那是完全正确的。您需要在这两列上创建一个UNIQUE索引,如下所示:

ALTER TABLE userTakingModule ADD UNIQUE INDEX(idUser, ModuleID);

现在,冲突将触发更新功能。您只需要从查询中完全删除userTakingModuleID列,即可根据需要自动为其提供一个值。您还会误用VALUES函数;您应该为它传递一个列名,它将解析为该列中插入的值而不会发生冲突。因此,您可以使用VALUES函数的 或变量本身。

说到变量,如果我不指出直接将变量插入查询中是多么不安全和危险的话,我将不知所措。您应该始终使用准备好的语句。您没有提供足够的代码来知道您使用的是哪个数据库API,但是对于PDO,它看起来像这样:

  $idUsers = $_SESSION['id'];
  $ModuleID = 5;
  $checkPoint = 999;

  $query= "INSERT INTO userTakingModule (idUsers, ModuleID, checkPoint) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE idUsers = VALUES (idUsers), ModuleID = VALUES (ModuleID), checkPoint = VALUES (checkPoint)";
  $stmt = $conn->prepare($query);
  $stmt->execute([$idUsers, $ModuleID, $checkPoint]);
  $data = $stmt->fetchAll(\PDO::FETCH_ASSOC);

对于mysqli这样的东西(尽管我不太熟悉)

  $idUsers = $_SESSION['id'];
  $ModuleID = 5;
  $checkPoint = 999;

  $query= "INSERT INTO userTakingModule (idUsers, ModuleID, checkPoint) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE idUsers = VALUES (idUsers), ModuleID = VALUES (ModuleID), checkPoint = VALUES (checkPoint)";
  $stmt = $conn->prepare($query);
  $stmt->bind_param("iii", $idUsers, $ModuleID, $checkPoint);
  $stmt->execute();
  $result = $stmt->get_result();