【问题标题】:MySQL UPSERT without ON DUPLICATE KEY没有 ON DUPLICATE KEY 的 MySQL UPSERT
【发布时间】:2014-03-25 15:39:45
【问题描述】:

我想要一个带有这些字段的 MySQL 表上的 UPSERTUPDATE 如果存在,否则插入):

CREATE TABLE item (
  uid int(11) NOT NULL AUTO_INCREMENT,
  timestamp int(11) NOT NULL DEFAULT '0',
  category1 int(11) NOT NULL DEFAULT '0',
  category2 int(11) NOT NULL DEFAULT '0',
  counter int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (`uid`)
)

此表已投入生产使用,(timestamp,category1,category2) 的组合是我的 INSERT 唯一的,但不是整个表内容。这就是我不能使用“ON DUPLICATE KEY”功能的原因。

关于 UNIQUE 问题的说明: 如果 category1=9 那么这是我的插入,(timestamp,category1,category2) 是唯一的。但该表已用于生产用途,如果 category1=1,2 则 (timestamp,category1,category2) 不是唯一的。 据我所知,我无法添加 UNIQUE 键,因为它会在类别 1+2 中产生问题。

我需要的是这样的:

 IF (timestamp,category1,category2) exists 
     counter=existingCount + newCount
 ELSE 
     insert new record

我使用 PHP 和 MySQL,因此两种语言的任意组合都可以。

我已经尝试过,但花费太多时间的是:

  • 单个 PHP SELECT 语句,然后是 UPDATEINSERT
  • INSERT 一切,然后 UPDATEDELETE 重复行

感谢我现在创建此存储过程的答案,语法正常但过程不起作用:

DROP PROCEDURE IF EXISTS myUpsert;
DELIMITER |
CREATE PROCEDURE myUpsert (IN v_timestamp INT, IN v_category1 INT, IN v_category2 INT, IN v_counter INT)        
BEGIN
  DECLARE existingCounter INT;
  SELECT COUNT(counter) AS existingCounter from item 
  WHERE timestamp =v_timestamp  AND category1=v_category1 AND category2=v_category2;

  IF existingCounter=0 THEN
    INSERT INTO item (timestamp,category1,category2,counter) 
    VALUES (v_timestamp,v_category1,v_category2,v_counter);
  ELSE
    UPDATE item SET count=v_counter+existingCounter
    WHERE timestamp=v_timestamp AND category1=v_category1 AND category2=v_category2;
  END IF;
END
|
DELIMITER ;

【问题讨论】:

  • 你能显示你试过的代码吗?不仅仅是描述
  • 插入重复键?
  • 您的表中是否存在唯一的列组合?如果是这样,请为他们添加一个UNIQUE 密钥并使用ON DUPLICATE KEY UPDATE
  • 您要在表中插入/更新的记录吗?
  • 如果单选 +(插入或更新)太慢,您是否尝试过执行 upsert 存储过程? stackoverflow.com/questions/14785155/…

标签: php mysql database upsert


【解决方案1】:

我建议为这三列添加唯一索引:

ALTER TABLE 项目添加唯一(时间戳、类别 1、类别 2)

【讨论】:

  • 我相信 OP 表明该组列在表中不是唯一的。
【解决方案2】:
DROP PROCEDURE IF EXISTS myUpsert;
DELIMITER |
CREATE PROCEDURE myUpsert (IN v_timestamp INT, IN v_category1 INT, IN v_category2 INT, IN v_counter INT)        
BEGIN
DECLARE existingCounter INT;
  SET existingCounter = (SELECT COUNT(counter) from item 
  WHERE timestamp =v_timestamp  AND category1=v_category1 AND category2=v_category2);

IF existingCounter=0 THEN
 INSERT INTO item (timestamp,category1,category2,counter) 
 VALUES (v_timestamp,v_category1,v_category2,v_counter);
ELSE
 UPDATE item SET count=v_counter+existingCounter
 WHERE timestamp=v_timestamp AND category1=v_category1 AND category2=v_category2;
 END IF;
END
|
DELIMITER ;

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-04
相关资源
最近更新 更多