2013-01-10 82 views
6

一直在网上寻找一段时间,似乎没有能够遇到任何类似于我想要的东西。我知道这是我写我的查询的方式,但任何帮助将不胜感激。MYSQL INSERT或UPDATE IF

的什么,我试图做的基础是:

  • 插入一些项目到一个表,如果不存在
  • 更新的项目,如果它确实存在

它的存在格式:

名称,条码,商品,数量,地点,价格和日期

名称 - 可用于多行 条码 - 用于特定项目,但可用作多个位置 项目 - 与条形码相同,但包含名称 数量 - 不言自明 位置 - 可以是不同的位置 价格 - 附加到特定项目 日期 - 上次购买该物品的时间

棘手的是,“名称”可以在不同地点有不同价格的多个项目(条形码和项目)。这个想法是,顾客可以看到他们在某个特定时间购买了多少物品,因此他们知道需要多少钱才能卖出它。

但是,他们购买的价格可能会有所不同,因此如果价格与以前的购买价格不同,他们需要在表格中创建另一行。

整个事情背后的想法是它记录每个地点每件商品的“名称”有多少,然后是他们在上次购买商品时购买的商品的价格。

希望是有道理的。

在伪代码:

Insert into table if does not exist 
    - name, barcode, item, quantity, location, price and date 
    If name, barcode, item, location and price are the same 
    - Update quantity and date (if more recent) 

回答

11

首先,名称,条码,物品,地点和价格增加UNIQUE约束。

ALTER TABLE tableX 
    ADD CONSTRAINT tableX_UQ 
    UNIQUE (name, barcode, item, location, price) ; 

然后你可以使用INSERT INTO ... ON DUPLICATE KEY UPDATE

INSERT INTO tableX 
    (name, barcode, item, location, price, quantity, date) 
VALUES 
    (?, ?, ?, ?, ?, ?, ?) 
ON DUPLICATE KEY UPDATE 
    quantity = CASE WHEN VALUES(date) > date 
       THEN quantity + VALUES(quantity)  -- add quantity 
       ELSE quantity       -- or leave as it is 
      END 
, date = CASE WHEN VALUES(date) > date 
       THEN VALUES(date) ;      -- set date to new date 
       ELSE date        -- or leave as it is 
      END 

REPLACE也可以使用,但也有在行为差异(如果你有外键,这尤其重要)。有关详细信息,请参阅此问题“INSERT IGNORE” vs “INSERT … ON DUPLICATE KEY UPDATE”和@Bill凯因其中讨论INSERT IGNORE之间的差异的答案,INSERT ... ON DUPLICATE KEYREPLACE

+0

奇妙的是,设法得到那个工作,但是,如果我只想要它更新如果日期更新,那么现有的,需要添加什么? – roadkill247

+0

如果它不是新的,保持原样?并只改变数量?或者让两者保持不变(那样在这种情况下什么都不做)? –

+0

嗨ypercude,是啊,如果日期不是更新,那么离开这两个不变更 – roadkill247

4

您可以在mysql中使用replace语法。

但是这只适用于需要唯一的字段上的唯一索引。

所以你必须创建这样一个唯一索引:

alter <yourtable> add unique index(name, barcode, item, location, price); 

那么你的插入/更新语法将成为

replace into <yourtable> (name, barcode, item, quantity, location, price, date) 
VALUES('name1', 'barcode1', 2, 'location1', 12.0, '25/12/2012'); 

编辑存储

例程序(简化和未经测试):

DELIMITER && 
DROP PROCEDURE IF EXISTS MyBase.UpdateOrInsert $$ 
CREATE PROCEDURE MyBase.UpdateOrInsert 
(
    IN _name VARCHAR(10), 
    IN _barcode VARCHAR(50), 
    IN _quantity INTEGER 
    IN _date DATE 
) 

DECLARE existingDate DATE default NULL; 
BEGIN 

SELECT date 
INTO existingDate 
FROM <yourTable> where name = _name and barcode = _barcode; 

if (existingDate IS NULL) then 
    insert into <yourtable> (name, barcode, quantity, date) VALUES(_name, _barcode, _qantity, _date); 
else 
    if (existingDate < _date) then 
    update <yourtable> 
    set quantity = _quantity, 
     date = _date 
    where name = _name 
    and barcode = _barcode; 
    end if; 
end if; 
END && 
+0

感谢您的回复,另一个有用的答案,但是,如果我想补充说,数量只有更新,如果日期是新的,那么当前在表中?正如我解析XML文件,所以一些数据被重新读取 – roadkill247

+0

@ roadkill247我认为你不能这样做ypercube的答案我的我...我会说你必须去存储过程。或者在进入数据库之前,在解析xml文件时进行管理...因为独特索引(这是两个答案的基础)可以管理唯一性,而不是“更大”/“更低”的条件。 –

+0

感谢您的快速回复。 XML我不能改变,因为它是由第三方提供的,所以当你说存储过程时,你的意思是什么? – roadkill247

1

感谢上述人员的帮助,我最终发现的解决方案非常接近两者。在下面找到它:

INSERT INTO `stock` 
    (name, barcode, item, quantity, location, price, date) 
VALUES 
    (?,?,?,?,?,?,?)       
ON DUPLICATE KEY UPDATE 
    quantity = CASE WHEN 
       VALUES(date) < $date 
       THEN quantity + $quantity 
       ELSE quantity 
       END, 
    date = CASE WHEN 
       VALUES(date) < $date 
       THEN VALUES(date) 
       ELSE $date 
       END 
+0

尽管使用这种方法遇到了一些有趣的问题,但是当我使用少量值时,它可以正常工作,但是即使日期与最后一次使用的日期相等,数量也会更新 – roadkill247