Delete with inner join and trigger throw error: Can't update table 'table_b' in stored function/trigger
Delete with inner join and trigger throw error: Can't update table 'table_b' in stored function/trigger
为什么会出现以下错误 (Can't update table 'table_b' in stored function/trigger because it is already used by statement which invoked这个存储 function/trigger) 在我尝试使用内部连接删除后出现?
我能解决吗?
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,
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),
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
中删除。
有了这个 set-up(并且没有触发器),您的两个 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
);
为什么会出现以下错误 (Can't update table 'table_b' in stored function/trigger because it is already used by statement which invoked这个存储 function/trigger) 在我尝试使用内部连接删除后出现? 我能解决吗?
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,
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),
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
中删除。
有了这个 set-up(并且没有触发器),您的两个 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
);