MySQL多删除2个表中的Might相互引用的行

时间:2016-02-03 07:16:42

标签: mysql

我有2个MySQL表,其中(InnoDB)外键相互进入。例如,

-- Adminer 4.2.3 MySQL dump

SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';

DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `null_or_b_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `null_or_b_id` (`null_or_b_id`),
  CONSTRAINT `a_ibfk_1` FOREIGN KEY (`null_or_b_id`) REFERENCES `b` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `a` (`id`, `null_or_b_id`) VALUES
(1, NULL),
(2, 2),
(4, 3),
(3, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8);

DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `null_or_a_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `null_or_a_id` (`null_or_a_id`),
  CONSTRAINT `b_ibfk_1` FOREIGN KEY (`null_or_a_id`) REFERENCES `a` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `b` (`id`, `null_or_a_id`) VALUES
(1, NULL),
(8, NULL),
(2, 2),
(4, 3),
(3, 4),
(5, 6),
(6, 7),
(7, 8);

-- 2016-02-03 06:45:07

我想要做的是从a中删除带有id 1,2,3和5的记录,并删除由于外键约束而需要在a和b中删除的所有记录。我试过了:

delete from a where a.id in (1,2,3,5);

delete a,b from a left join b on b.null_or_a_id = a.id where a.id in (1,2,3,5);

以上两者都给出了同样的错误:

Error in query (1451): Cannot delete or update a parent row: a foreign key constraint fails (`test/multi_delete_with_references`.`b`, CONSTRAINT `b_ibfk_1` FOREIGN KEY (`null_or_a_id`) REFERENCES `a` (`id`))

即使我删除了在。

中定义的b上的外键约束,我也会得到相同的错误

我不能做的事情:

  • 禁用外键检查:因为这两个表也被其他表引用,我不希望这些表有孤立的行,如果这个删除会导致这样的孤立行,我需要删除这个删除。
  • 首先从子表中删除:因为您可以看到在两个表中都有id为2的行的情况下,它们相互引用,因此在没有其他表的情况下不能删除它们,对于具有ID的行也是如此在两个表中都是3和4,它们形成了一个自引用链。

我查看了答案here,但这对我不起作用,因为这两个表互相引用。

有没有办法解决这个问题?

顺便说一句,我也尝试动态生成复杂的嵌套查询,但结果却是无穷无尽的:

delete from a where id in (1,2,3,5);
delete from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where id in (1,2,3,5)) x);
delete from a where null_or_b_id is not null and null_or_b_id in (select * from (select id from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where id in (1,2,3,5)) x)) x);
delete from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where null_or_b_id is not null and null_or_b_id in (select * from (select id from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where id in (1,2,3,5)) x)) x)) x)
...

1 个答案:

答案 0 :(得分:0)

您的问题与this one非常相似,并且same solution适用:首先通过在您要删除的行中设置NULL引用列来删除引用。然后删除。