如何解决MySQL更新,但删除重复键由于唯一索引
我正在寻找有关更新数据库表中几行的一些见解,这些行又会违反表的唯一索引。在某些情况下:
我有一个多对多联接表,该表定义了其他两个表之间的关系。该表上有一个唯一索引,该索引指出子表外键对于单个父表必须是唯一的。例如:
=============================
| ID | Parent ID | Child ID |
-----------------------------
| 1 | 1 | 1 |
| 1 | 1 | 2 |
| 1 | 1 | 3 |
| 1 | 2 | 1 |
| 1 | 2 | 2 |
| 1 | 3 | 1 |
=============================
我需要弃用某些允许的Child ID
值,并将那些现在已弃用的ID映射到它们的未弃用的值。 (例如:在上面的示例中,如果我们弃用3
=> 2
,则将导致唯一索引冲突,因为Parent 1
和Child 2
之间已经存在关系)
问题: 有没有一种方法可以处理唯一索引冲突,而只需删除正在更新的当前行?
我知道MysqL中有一个INSERT ON DUPLICATE KEY UPDATE
子句,但是有一个UPDATE ON DUPLICATE KEY DELETE
吗?我认为我们甚至可以接受在执行更新之前删除导致唯一索引的行。 (例如:UPDATE ON DUPLICATE KEY DELETE EXISTING ROW
之类的东西)
仅尝试避免超级复杂的sql迁移,如果可能的话,该迁移更容易出错。
感谢您的帮助或提示,如果您需要更多信息,请告诉我,我们会尽我所能提供。
更新:多亏了Bill的回答,我才得以提出以下sql过程:
DELIMITER $$
CREATE PROCEDURE `migrate_deprecated_children`()
BEGIN
DECLARE `_rollback` BOOL DEFAULT 0;
DECLARE CONTINUE HANDLER FOR sqlEXCEPTION SET `_rollback` = 1;
START TRANSACTION;
-- Insert new items,ignoring any that already exist
INSERT IGnorE INTO JOIN_TABLE (PARENT_ID,CHILD_ID)
SELECT PARENT_ID,(CASE
WHEN CHILD_ID = 106 THEN 68
WHEN CHILD_ID IN (109,111,124,131) THEN 110
WHEN CHILD_ID IN (113,114) THEN 61
WHEN CHILD_ID = 115 THEN 48
WHEN CHILD_ID IN (118,143,169,77,86) THEN 3
WHEN CHILD_ID = 121 THEN -1
WHEN CHILD_ID = 127 THEN 102
WHEN CHILD_ID IN (134,80) THEN 173
WHEN CHILD_ID = 136 THEN 50
WHEN CHILD_ID = 145 THEN 56
WHEN CHILD_ID = 146 THEN 0
WHEN CHILD_ID IN (14,15) THEN 37
WHEN CHILD_ID = 54 THEN 94
WHEN CHILD_ID IN (84,99) THEN 13
WHEN CHILD_ID = 87 THEN 83
WHEN CHILD_ID = 91 THEN 96
WHEN CHILD_ID = 98 THEN 30
ELSE CHILD_ID
END) as CHILD_ID
FROM JOIN_TABLE;
-- Delete all deprecated rows
DELETE FROM JOIN_TABLE WHERE CHILD_ID IN (14,15,54,80,84,86,87,91,98,99,106,109,113,114,115,118,121,127,131,134,136,145,146,169);
IF `_rollback` THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END$$
DELIMITER ;
再次感谢!
解决方法
MySQL不支持执行您所描述的任何SQL语句。
最简单的解决方案是以下两个步骤:
INSERT IGNORE INTO m2mtable (id,parent_id,child_id)
SELECT id,2
WHERE child_id = 3;
DELETE FROM m2mtable WHERE child_id = 3;
您应该将两个语句都包装在一个事务中,以使更改对于其他任何客户端来说都是原子性的。
并非每个任务都必须在单个SQL语句中完成。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。