【问题标题】:Delete with inner join and trigger throw error: Can't update table 'table_b' in stored function/trigger使用内部联接删除并触发抛出错误:无法在存储的函数/触发器中更新表“table_b”
【发布时间】:2020-12-08 01:58:27
【问题描述】:

为什么会出现以下错误(无法更新存储函数/触发器中的表 '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,
  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;

【问题讨论】:

  • 我可以只使用 another_table_id 23 删除 table_a 吗?

标签: mysql sql triggers subquery sql-delete


【解决方案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
);

【讨论】:

  • 我从来不知道 on delete cascade 表达式
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
  • 2013-02-24
  • 1970-01-01
  • 2020-03-10
相关资源
最近更新 更多