使用内部联接进行删除并触发引发错误:无法更新存储的函数/触发器中的表'table_b'

问题描述

为什么出现以下错误( 无法更新存储函数/触发器中的表'table_b',因为调用该存储函数/触发器的语句已使用该表 )我尝试使用内部联接删除后出现? 我可以解决吗?

DROP TABLE if exists table_b;
DROP TABLE if exists table_a;

CREATE TABLE table_a (
  id int auto_increment,name varchar(255) DEFAULT NULL,primary key (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

DROP TABLE if exists table_b;
CREATE TABLE table_b (
  id int auto_increment,id_table_a int NOT null,another_table_id int NOT null,foreign key (id_table_a) references table_a(id),primary key (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

DELIMITER $$
drop trigger if exists tg_test$$
create trigger tg_test before delete on table_a for each row
begin
  delete from table_b where id_table_a = OLD.id;
end$$

DELIMITER ;

insert into table_a(name) values('t-a');
insert into table_b(name,id_table_a,another_table_id) values('t-b',1,23);

-- Error Can't update table 'table_b' in stored function/trigger because it is already used by statement which invoked this stored function/trigger
-- in any of this two lines
delete table_a from table_a inner join table_b on table_b.id_table_a = table_a.id where another_table_id = 23;
delete from table_a where id in (select id_table_a from table_b where another_table_id = 23);

-- Success
delete from table_a where id = 1;

解决方法

我在这里看不到触发点。只需在外键的声明中添加on delete cascade选项即可实现所需的功能:

CREATE TABLE table_b (
  id int auto_increment,name varchar(255) DEFAULT NULL,id_table_a int NOT null,another_table_id int NOT null,foreign key (id_table_a) references table_a(id) on delete cascade,primary key (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

现在无论何时从table_a删除记录,子记录(由外键定义指定)都将从table_b中删除。

有了这个设置(没有触发器),您的delete语句都可以正常运行。我实际上会使用exists而不是joinin,但这主要取决于口味:

delete from table_a 
where exists( 
    select 1 
    from table_b b 
    where b.id_table_a = table_a.id and b.another_table_id = 23
);

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...