更新行,如果更新失败,则删除同一行

时间:2017-11-17 18:06:24

标签: mysql sql

我有一个汇总项目及其类别的表格。一个项目可以有多个类别。这是简化的模式和示例数据:

表名:xref,(itemID,catID)定义为主键

itemID | catID
-------+-------
4059   | 159
4059   | 219

我还有一个类别合并功能。执行此操作时,我还将源类别中链接的产品移动到目标(合并)类别。对于将项目从类别159移动到219,我使用这样的SQL:

UPDATE `xref` SET `catID` = 219 WHERE `catID` = 159

但更新失败,因为已经存在4059-219(PK约束)。

期望的结果是

itemID | catID
-------+-------
4059   | 219

我无法在数据库上使用存储过程或函数,但可以在我的应用程序中实现所需的步骤。

  • 当UPDATE查询失败时,有没有办法删除行?
  • 如何编写一个"预测"要失败的UPDATE查询行?类似于"返回itemID' s同时具有catIDÛ 159"。 SELECT * FROM xref WHERE catID IN (159, 219) GROUP BY itemID HAVING COUNT(*) >= 2是一种正确的方法吗?

3 个答案:

答案 0 :(得分:1)

我无法使用@ JNevill的方法,因为我事先并不知道受影响的项目ID。但这让我对这个两步解决方案有所了解。

UPDATE IGNORE `xref` SET `catID` = 219 WHERE `catID` = 159
DELETE FROM `xref` WHERE `catID` = 159

感谢所有其他答案/评论。

答案 1 :(得分:0)

尝试以下查询:

UPDATE `xref` 
SET `catID` = 219 
WHERE `catID` = 159
and `itemID` not in (select 'itemID' 
                     from (select *from 'xref') x
                     where 'catID' = 219)
;

希望它有所帮助!

答案 2 :(得分:0)

这种方式会暂时删除您的约束以允许更新,然后将它们放回到最后。

如果您的数据库是生产数据库 TEST ON A COPY!

# set up tables for the purpose of this example
CREATE TABLE Item
(
    ItemId INT,
    ItemName VARCHAR(255),
    PRIMARY KEY (ItemId)
);

 CREATE Table Category
 (
     CatId INT,
     CatName VARCHAR(255),
      PRIMARY KEY (CatId)
 );

 CREATE TABLE xref
(
    ItemId INT,
    CatId INT,
    PRIMARY KEY (ItemId,CatId),
    FOREIGN KEY (ItemID) REFERENCES Item(ItemId),
    FOREIGN KEY (CatId) REFERENCES Category(CatId)
 );

 # insert data for the purpose of this example
 INSERT INTO Item
 VALUES
 (1,'Hammer'),
 (2,'Chisel'),
 (3,'Wrench');

 INSERT INTO Category
 VALUES
 (159,'Tool'),
 (219,'Toy'),
 (3,'foo');

 INSERT INTO xref
 VALUES
 (1,159),
 (1,219),
 (2,159),
 (3,3);

 START TRANSACTION;

# remove constraints so we can run the update
ALTER TABLE xref DROP FOREIGN KEY xref_ibfk_1;
ALTER TABLE xref DROP FOREIGN KEY xref_ibfk_2;
ALTER TABLE xref DROP PRIMARY KEY;

# Update the categories
UPDATE xref SET CatId = 219 WHERE CatId = 159;

# Copy the table into a tmep table but exclude duplicates we have created above
CREATE TEMPORARY TABLE IF NOT EXISTS xref_tmp AS (SELECT DISTINCT
                                                           ItemId,
                                                           CatId
                                                    FROM    xref);

# Empty the original table
DELETE FROM xref;

# Copy the clean results back to the orginal table
INSERT INTO xref
SELECT * FROM xref_tmp;

# put our constaints back
ALTER TABLE xref ADD PRIMARY KEY (ItemId,CatId);
ALTER TABLE xref ADD FOREIGN KEY (ItemID) REFERENCES Item(ItemID);
ALTER TABLE xref ADD FOREIGN KEY (CatID) REFERENCES Category(CatID);

COMMIT