MYSQL INSERT或UPDATE IF

roa*_*247 6 mysql sql database

一直在网上浏览一段时间,似乎没有能够遇到任何类似于我想要的东西.我知道这与我编写查询的方式有关,但任何帮助都会受到赞赏.

我想要做的基础是:

  • 如果某些项不存在,请将其插入表中
  • 更新项目(如果存在)

它以以下格式存在:

名称,条形码,项目,数量,位置,价格和日期

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

棘手的是,"名称"可以在不同的位置有几个项目(条形码和项目),价格不同.我们的想法是,客户可以看到他们在一定时间内购买了多少物品,因此他们知道他们需要多少钱来销售它.

然而,他们购买它的价格可能会有所不同,因此如果价格与之前的购买价格不同,他们需要在表格中创建另一行.

整个事情背后的想法是它记录每个位置的每个项目的"名称"有多少,然后记录他们上次购买时的价格.

希望有道理.

在伪代码中:

    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)
Run Code Online (Sandbox Code Playgroud)

ype*_*eᵀᴹ 13

首先,UNIQUE在名称,条形码,项目,位置和价格上添加约束.

ALTER TABLE  tableX
  ADD CONSTRAINT tableX_UQ
    UNIQUE (name, barcode, item, location, price) ;
Run Code Online (Sandbox Code Playgroud)

然后你可以使用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 
Run Code Online (Sandbox Code Playgroud)

REPLACE也可以使用,但行为存在差异(如果你有外键,这尤其重要).有关详细信息,请参见该问题"插入忽略"与"INSERT ... ON DUPLICATE KEY UPDATE"和@Bill凯因其中讨论之间的差别的答案INSERT IGNORE,INSERT ... ON DUPLICATE KEYREPLACE.


Rap*_*aus 5

你可以在mysql中使用replace语法.

但这只适用于......需要独特的字段的唯一索引.

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

alter <yourtable> add unique index(name, barcode, item, location, price);
Run Code Online (Sandbox Code Playgroud)

那么你的插入/更新语法就会变成

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

编辑

存储过程示例(简化和未测试):

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 &&
Run Code Online (Sandbox Code Playgroud)