【问题标题】:MySQL Trigger - delete after updateMySQL 触发器 - 更新后删除
【发布时间】:2011-08-25 11:47:38
【问题描述】:
对于一个项目中的测试用例,如果其中一个字段满足其中一个条件,我必须删除记录。
最简单的似乎是简单的触发器:
delimiter $$
drop trigger w_leb_go $$
create trigger w_leb_go after update on test
for each row
begin
set @stat=NEW.res;
set @id=NEW.id;
IF @stat=3 THEN
delete from test where id=@id;
END IF;
end$$
delimiter ;
但我怀疑有错误:
更新测试集 res=3 where id=1;
错误 1442 (HY000): 无法更新存储函数/触发器中的表“测试”,因为它已被调用此存储函数/触发器的语句使用。
只有通过访问数据库才能做到这一点?我的意思是我不应该更改经过测试的应用程序。
【问题讨论】:
标签:
mysql
sql
triggers
sql-update
sql-delete
【解决方案1】:
您可能需要做的是使用触发器的“BEFORE INSERT”来检查所添加的记录是否无效。
这个 SO 问题提供了有关如何处理无效记录的一些详细信息:Prevent Insert
另一种方法是修改您的程序以将记录插入另一个表,该表具有清除所需表的触发器。
【解决方案2】:
在触发器内部,您无法更改触发器所属的表。
你也不能间接改变那张桌子。
不过,您还可以做一些其他事情。如果您不删除一行,而是添加一个字段deleted,那么您可以像这样标记它已删除。
delimiter $$
drop trigger w_leb_go $$
CREATE TRIGGER w_leb_go BEFORE UPDATE ON test FOR EACH ROW
BEGIN
IF NEW.res=3 THEN
SET NEW.deleted = 1;
END IF;
END$$
delimiter ;
请注意,如果要更改行中的任何内容,触发器必须是 before。
或者,您可以向某个临时表添加删除提醒,并在更新语句之后测试该表。
CREATE TRIGGER au_test_each AFTER UPDATE ON test FOR EACH ROW
BEGIN
IF NEW.res=3 THEN
INSERT INTO deletion_list_for_table_test (test_id) VALUE (NEW.id);
END IF;
END$$
现在您需要将更新语句更改为:
START TRANSACTION;
UPDATE test SET whatever to whichever;
DELETE test FROM test
INNER JOIN deletion_list_for_table_test dt ON (test.id = dt.test_id);
DELETE FROM deletion_list_for_table_test WHERE test_id > 0 /*i.e. everything*/
COMMIT;
当然,如果您标记您的行,您可以将删除代码简化为:
START TRANSACTION;
UPDATE test SET whatever to whichever;
DELETE FROM test WHERE deleted = 1;
COMMIT;
【解决方案3】:
我的几分钱:-
添加“已删除”列被视为表结构中的更改。
因此,除非是新开发,否则不推荐。
如果是遗留应用程序,最好 -
向某个临时表添加删除提醒,并在更新语句之后测试该表。