2017-07-19 84 views
-2

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

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。如果没有更改,受影响的行是0,即使记录已经存在。但是这会触发INSERT语句。这一个失败,因为user_id字段是唯一的,现在我忽略这个,所以我的代码工作正常。

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

+0

使USER_ID int和不串并检查 – Exprator

+0

执行插入或更新之前,简单地火一把'SELECT查询来获取计算该用户id'。如果计数是1,则执行更新,否则执行插入。 –

回答

4

可以使用INSERT ... ON DUPLICATE KEY

使用这种方法会事务安全,因为MySQL是处理它在一个隐式事务解决这个问题。您当前的方法允许在两个并发请求可能相互干扰的情况下进行分割。

假设你在MySQL 5.7:https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html

您的查询应该是这样的:

INSERT INTO user_meta SET user_id = 125, active = 0 
    ON DUPLICATE KEY UPDATE active = 0 

更新: 只是为了解释为何当前的方法是事务性不安全,想象两个并发请求并行执行。

  1. 请求1尝试更新,看到0受影响的行。
  2. 请求2尝试更新,看到0受影响的行。
  3. 请求1插入新记录。
  4. 请求2插入新记录。

无论您明确开始和完成交易,或者是否隐含做(例如,通过INSERT ... ON DUPLICATE KEY)MySQL将负责确保上述故障的情况下不通过阻断第二个请求发生的责任直到第一次结束。

4

MySQL有此内置的解决方案 - on duplicate key update条款:

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

用mysql ON DUPLICATE KEY UPDATE检查已经存在于数据库或不予备案。你的餐桌必须有一个有unique类型的列。这里您的user_id列是唯一类型。检查机制的文档here

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