MySQL触发器

  • 触发器的触发事件有:updateinsertdelete,触发时机分为事件前,事件后
  • 触发器是存在每张表中,2张表中触发器名称可重复,同张表中触发器不允许重名
  • 触发器的调用是被动的,换句话说:SQL执行,触发对应触发器

创建触发器

create trigger 触发器名 before/after insert/update/delete on 表名 for each row
begin
	具体执行内容
end

删除触发器

drop trigger 表名.触发器名

attention!

如果你希望动手自己试试,请按照我提供的这张表👇,我下面的实例代码的试验对象就是这张表

/*建表语句*/
create table bill (
    title varchar(20) default ' ' comment '品名',
    pay int default 0 comment '售价',
    price int default 0 comment '价格',
    repertory int default 0 comment '库存',
    create_time datetime default null comment '创建时间'
);
/*历史表*/
create table bill_copy (
    title varchar(20) default ' ' comment '品名',
    pay int default 0 comment '售价',
    price int default 0 comment '价格',
    repertory int default 0 comment '库存'
);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k1', 1, 8, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k2', 2, 7, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k3', 3, 6, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k4', 4, 5, 5, null);
INSERT INTO bill (title, pay, price, repertory, create_time) VALUES ('k5', 5, 4, 6, null);

新增前

注意:可以操作本表中当前行

/*创建触发器:在新增每条记录前对create_time字段赋值*/
create trigger insert_trigger_before before insert on bill for each row
begin
	set NEW.create_time = now();
end;

调用

insert into bill(title,pay,price,repertory) values ('k7',6,3,6);

结果

title pay price repertory create_time
k7 6 3 6 2022-12-29 13:39:51

新增的时候不能使用操作目标表中数据!比如这种👇,就是错误的!!!

create trigger insert_trigger_before before insert on bill for each row
begin
	update bill set create_time = now() where title = NEW.title;
end;

操作其他表中的数据,是没有问题的,比如

create trigger insert_trigger_before_2 before insert on bill for each row
begin
        insert into bill_copy(title, pay, price, repertory) VALUES (NEW.title,NEW.pay,NEW.price,NEW.repertory);
end;

bill中插入一条数据时会调用☝️触发器,bill_copy中也会新增一条数据。

新增后

注意:不能操作表中数据

create trigger insert_trigger after insert on bill
for each row SELECT NEW.title into @newTitle;

调用

insert into bill(title,pay,price,repertory) values ('k8',7,2,6);
select @newTitle; -- 返回 k8

更新前

注意:可以操作本表中当前行数据

/*每次更新,把title转小写*/
create trigger update_trigger_before before update on bill for each row
begin
	set NEW.title = lower(NEW.title);
end;

调用

update bill set title = 'K8' where title = 'k8';

执行☝️后,表中k8的大小写不会发生改变!

更新后

注意:无法操作本表中数据

/*更新bill表中数据后,按title索引备份表,并更新对应数据的创建时间*/
create trigger update_trigger_after after update on bill for each row
begin
    update bill_copy set create_time = now() where title = NEW.title;
end;

如果update的对象不是备份表,而是bill表,那么当你创建好触发器,执行update语句时会发现,无论如何执行都会报错!这是因为更新后,不能操作本表,操作其他表中数据是没有问题的。

删除前

/*删除前把数据写入备份表中*/
create trigger delete_trigger_before before delete on bill for each row
begin
insert into bill_copy(title, pay, price, repertory)
    values(old.title, old.pay, old.price, old.repertory);
end;

删除后

/*删除后把数据写入备份表中*/
create trigger delete_trigger_after after delete on bill for each row
begin
    insert into bill_copy(title, pay, price, repertory) values(old.title, old.pay, old.price, old.repertory);
end;

调用

delete from bill where title = 'k1';

执行SQL,打开bill_copy表,发现bill_copy表中多了一条记录,证明触发器执行,且成功!

扩展知识点

触发器中有2个变量:new,old,使用最多!分别代表新值和旧值

  • update时,可用new,old
  • insert时,用new
  • delete时,用old

触发器支持存储过程,却不支持调用存储过程,如果要用到存储过程,只有重新手写,不能使用call 存储过程名样的代码。

posted @ 2022-12-29 15:09  勤匠  阅读(121)  评论(0编辑  收藏  举报