LOADING

加载过慢请开启缓存 浏览器默认开启

Mysql触发器对同一张表进行操作

触发器初始结构:

DELIMITER $$
CREATE
TRIGGER `数据库名`.`触发器名` BEFORE/AFTER INSERT/UPDATE/DELETE
ON `数据库名`.`表名`
FOR EACH ROW BEGIN
-- 逻辑、条件语句
END$$
DELIMITER ;

目的:当一张表中的某个字段值更新为特定值时,触发更新本条数据的另一字段值

( 示例:根据 prj_base_info 表中的 project_status 的值判断是否是600时,触发更新同表的 complete_time 字段的时间为系统当前时间 )

开始写出的触发器如下所示

DROP TRIGGER IF EXISTS update_complete_time;
DELIMITER $
CREATE TRIGGER update_complete_time AFTER UPDATE
ON prj_base_info FOR EACH ROW
BEGIN
IF (new.project_status=600)
THEN
UPDATE prj_base_info
SET complete_time =DATE_FORMAT(NOW(), '%Y-%m-%d')
WHERE prj_base_info.id = new.id;
END IF;
END $

执行结果没有问题,创建触发器成功,但是执行 update 语句进行测试如下报错,提示:无法更新存储函数/触发器中的表 ‘prj_base_info’,因为它已经被调用此存储函数/触发器的语句使用。

1 queries executed, 0 success, 1 errors, 0 warnings

查询:update prj_base_info set type=2,project_status=600 where id=’1537842899333’

错误代码: 1442

Can't update table 'prj_base_info' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.

通过查阅资料了解,同表的更新不能在触发器里使用 update,而是直接使用set

修改为:

DROP TRIGGER IF EXISTS update_complete_time;
DELIMITER $
CREATE TRIGGER update_complete_time AFTER UPDATE
ON prj_base_info FOR EACH ROW
BEGIN
IF (new.project_status=600)
THEN
SET new.complete_time =DATE_FORMAT(NOW(), '%Y-%m-%d');
END IF;
END $

结果发现还报错。。。

错误代码: 1362

Updating of NEW row is not allowed in after trigger

把 AFTER 修改为BEFORE即可:

DROP TRIGGER IF EXISTS update_complete_time;
DELIMITER $
CREATE TRIGGER update_complete_time BEFORE UPDATE
ON prj_base_info FOR EACH ROW
BEGIN
IF (new.project_status=600)
THEN
SET new.complete_time =DATE_FORMAT(NOW(), '%Y-%m-%d');
END IF;
END $

BEFORE 与 AFTER 区别:

BEFORE:( insert、update )可以对 new 进行修改,AFTER 不能对 new 进行修改,两者都不能修改 old 数据。

对于 INSERT 语句, 只有 NEW 是合法的;

对于 DELETE 语句,只有 OLD 才合法;

对于 UPDATE 语句,NEW、OLD 可以同时使用。

总结:BEFORE 或 AFTER 关键字决定何时执行触发器动作,决定是在关联行的插入、修改或删除之前或者之后执行触发器动作。