我在MySQL中有一个触发器
DELIMITER $$
CREATE TRIGGER trigger2
BEFORE INSERT ON participated FOR EACH ROW
BEGIN
IF((SELECT COUNT(*) FROM participated WHERE driver_id = NEW.driver_id) > 3) THEN
DELETE FROM accident WHERE report_no = NEW.report_no;
SIGNAL SQLSTATE '45000' SET message_text = "Driver is already involved in 3 accciddents";
END IF;
END;$$
DELIMITER ;
首先将事故报告插入事故表。在插入参与表之前,如果涉及参与3次以上事故的驾驶员,则必须给出警告,并删除事故表中的驾驶员数据。
'accident' and 'participated' are the two tables.
accident(report_no,date,location);
participated(driver_id,reg_no,report_no,amount);
例如:
insert into accident values(34,"2022-04-05","bangalore");
insert into participated values("D1","KA-09-MM-5644",34,20000);
ERROR 1644 (45000): Driver is already involved in 3 accciddents
警告起作用,但未删除事故表中的行。事故表中仍有report_no 34
的行
1条答案
按热度按时间xwbd5t1u1#
Mysql触发器中的body部分就像一个ALL-OR-NOTHING事务。这意味着里面的每个查询都必须成功,否则整个过程都会被撤消。通过使用
SIGNAL SQLSTATE '45000' SET message_text
,故意引发一个错误,它会回滚到目前为止发生的每一件事,并返回一条消息。注意,INSERT语句本身会因为引发的错误而被取消。当然,可以通过在触发器的开头声明一个continue处理程序来忽略错误。这将确保在遇到SQLSTATE '45000'后继续运行。但是,message_text是IGNORED,因为它只用于处理警告/错误,而不是用于continue处理程序。遗憾的是,我们不能使用触发器返回结果集。因此,如果我们在SIGNAL语句后添加SELECT语句或类似语句,将弹出一个错误:
如果我们真的需要一条消息显示出来,我们可以考虑使用一个过程来绕过触发器所强加的限制:
通过使用过程,我们可以显示消息。如果我们直接使用insert语句(当我们忘记使用过程时),触发器的操作仍然适用。因此,我们可以考虑添加INSERT语句来填充审计表以供将来参考。