Mysql 更新行,如果更新失败,则删除同一行
我有一个汇总项目及其类别的表。一个项目可以有多个类别。以下是简化的模式和示例数据: 表名称:定义为主键的外部参照(itemID,catID)Mysql 更新行,如果更新失败,则删除同一行,mysql,sql,Mysql,Sql,我有一个汇总项目及其类别的表。一个项目可以有多个类别。以下是简化的模式和示例数据: 表名称:定义为主键的外部参照(itemID,catID) itemID | catID -------+------- 4059 | 159 4059 | 219 我还有一个类别合并功能。执行此操作时,我还将在源类别中链接的产品移动到目标(合并)类别。为了将项目从类别159移动到类别219,我使用如下SQL: UPDATE `xref` SET `catID` = 219 WHERE `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
我不能在数据库上使用存储过程或函数,但可以在应用程序中实现所需的步骤
- 当更新查询失败时,是否有方法删除行
- 如何编写一个“预测”将要失败的更新查询的行的查询?类似于“returnitemid是指同时拥有catID的219和159”。
是正确的方法吗SELECT*FROM xref,其中(159219)GROUP BY itemID中的catID具有COUNT(*)>=2
UPDATE `xref`
SET `catID` = 219
WHERE `catID` = 159
and `itemID` not in (select 'itemID'
from (select *from 'xref') x
where 'catID' = 219)
;
希望有帮助 这种方式暂时删除您的约束以允许更新,然后将它们放回末尾 如果您的数据库是生产数据库,请对副本进行测试强>
# 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
我不能使用@JNevill的方法,因为我不知道事先会受到itemID的影响。但这给了我一个两步解决方案的想法
UPDATE IGNORE `xref` SET `catID` = 219 WHERE `catID` = 159
DELETE FROM `xref` WHERE `catID` = 159
感谢您提供的所有其他答案/评论。您不能将“更新”调用放入try块中,如果失败(引发异常),请运行删除代码吗?当然,您需要确保您正在侦听要抛出的正确异常。您可以分两个步骤来完成此操作。步骤1:删除
itemid
的任何记录,其中catid
等于要将其更新到的内容。2) 运行更新。这似乎是倒退,对吗?但它肯定会成功的。谢谢。这将防止PK约束错误,但仍将幻影记录(4059 | 159)保留在数据库中。之后我仍然需要删除它。更新忽略也做同样的事情,但更短,所以我在回答中选择了它。你可以在更新之后删除它。但是是的,updateignore
将是一种更好的方法。