MYSQL更新或使用PHP插入

时间:2017-07-19 07:40:41

标签: php mysql sql upsert

我需要更新数据库中的记录,但我不知道该记录是否已存在。如果存在,请更新它,否则插入它。现在我想出了这段代码:

1: <?php
2: $query = "UPDATE user_meta SET active = '0' WHERE user_id = '125'";
3: $mysqli->query($query);
4: 
5: if($mysqli->affected_rows == 0){
6:     $query = "INSERT INTO user_meta (user_id, active) VALUES ('125', 0)";
7:     $mysqli->query($query);
8: }

表格:

CREATE TABLE `user_meta` (
  `user_id` int(11) DEFAULT NULL,
  `active` tinyint(4) DEFAULT NULL,
  UNIQUE KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这段代码对我来说很好,但它实际上会产生一个我忽略的错误。

问题出在这一行5。如果没有更改,则affected_rows为0,即使该记录已存在。但这会触发INSERT语句。这个失败是因为user_id字段是唯一的,现在我忽略了这一点,所以我的代码工作正常。

但这是要走的路吗? 或者我应该先做一个选择而不是更新或插入?

3 个答案:

答案 0 :(得分:4)

您可以使用INSERT INTO user_meta SET user_id = 125, active = 0 ON DUPLICATE KEY UPDATE active = 0

解决此问题

使用此方法在事务上是安全的,因为MySQL在一个隐式事务中处理它。您当前的方法允许分割时刻,其中两个并发请求可能会相互干扰。

假设您使用的是MySQL 5.7:https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

您的查询将如下所示:

INSERT ... ON DUPLICATE KEY

<强>更新 只是详细说明当前方法在事务上不安全的原因,想象两个并发请求并行执行。

  1. 请求1尝试更新,看到0个受影响的行。
  2. 请求2尝试更新,看到0个受影响的行。
  3. 请求1插入新记录。
  4. 请求2插入新记录。
  5. 您是显式启动并完成事务,还是隐式做(例如通过Client)MySQL将负责确保上述内容通过阻止第二个请求直到第一个请求结束,不会发生错误的情况。

答案 1 :(得分:4)

MySQL有一个内置的解决方案 - on duplicate key update子句:

INSERT INTO user_meta (user_id, active) 
VALUES (125, 0)
ON DUPLICATE KEY UPDATE active = 0

答案 2 :(得分:1)

使用mysql ON DUPLICATE KEY UPDATE来检查db中是否已存在记录。您的表必须具有unique类型的列。您的user_id列是唯一类型。查看文档here

INSERT INTO user_meta (user_id, active) 
VALUES (125, 0)
ON DUPLICATE KEY UPDATE active = 0