问题描述
为什么出现以下错误( 无法更新存储函数/触发器中的表'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
而不是join
或in
,但这主要取决于口味:
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
);