一、触发器概述
1.开发场景
有2个相互关联的表,商品信息和库存信息表。在添加一条新商品记录时,为了保证数据完整性,在库存表添加一条库存记录。
把两个关联操作步骤写到程序里面,用事务包裹起来,确保两个操作成为一个原子操作,要么全部执行,要么全部不执行。
除了事务,还可以创建一个触发器,让商品信息数据的插入操作自动触发库存数据的插入操作。
2.触发器概述
触发器是由事件来触发某个操作,这些事件包括insert,update,delete事件。所谓事件是用户的动作或者触发某项行为。如果定义触发程序,当数据库执行这些语句时候,就相当于事件发生了。就会自动激发触发器执行相应的操作。
3.触发器的创建
说明
表名:表示触发器监控的对象
before|after:表示触发的时间,before在事件之前触发,after在事件之后触发。
insert|update|delete:表示触发的事件
4.代码实现
准备
create table test_trigger(
id int primary key auto_increment,
t_note varchar(30)
);create table test_trigger_log(
id int primary key auto_increment,
t_log varchar(30)
);
创建触发器1
创建名称为before_insert的触发器,向test_trigger数据表插入数据之前,向test_trigger_log数据表中插入before_insert的日志信息。
delimiter $
create trigger before_insert
before insert on test_trigger
for each row
begin
insert into test_trigger_log(t_log)
values ('before_insert');
end $
delimiter ;
测试
insert into test_trigger(t_node)
values
('测试数据1')
创建触发器2
创建名称为after_insert的触发器,向test_trigger数据表插入数据之后,向test_trigger_log数据表中插入after_insert的日志信息。
delimiter $
create trigger after_insert
after insert on test_trigger
for each row
begin
insert into test_trigger_log(t_log)
values('after_insert');
end $
delimiter ;
测试
insert into test_trigger(t_node)
values
('测试数据2')
创建触发器3
定义触发器“salary_check_trigger”,基于员工表“employees”的INSERT事件,在INSERT之前检查将要添加的新员工薪资是否大于他领导的薪资,如果大于领导薪资,则报sqlstate_value为'HY000'的错误,从而使得添加失败。
delimiter $
create trigger salary_check_trigger
before insert on emp
for each row
begin
# 查看数据的manager的薪资
declare mgr_sal double;
select salary into mgr_sal from employees
where employee_id = new.manager_id;
# 判断
if new.salary > mgr_sal
then signal sqlstate 'HY000' set message_text='错误薪资不能高于领导薪资';
end if;
end $
delimiter ;
二、查看、删除触发器
1.查看当前数据的所有触发器
show triggers
2.查看创建触发器的定义
show create trigger 触发器名称
3.从系统库里面查询触发器的信息
SELECT * FROM information_schema.TRIGGERS;
4.删除触发器
drop trigger 触发器名称;
三、触发器的优缺点
1.触发器优点
①触发器可以确保数据的完整性
②触发器可以记录操作日志
③触发器在操作数据前,对数据的合法性进行检查
2.触发器缺点
①触发器的可读性差
②数据表结构的变更,触发器出错
四、触发器的练习
#0. 准备工作
CREATE TABLE emps
AS
SELECT employee_id,last_name,salary
FROM atguigudb.`employees`;
#1. 复制一张emps表的空表emps_back,只有表结构,不包含任何数据
create table emps_back
as
select * from atguigudb.employees
where 0
#2. 查询emps_back表中的数据
select * from emps_back
#3. 创建触发器emps_insert_trigger,每当向emps表中添加一条记录时,同步将这条记录添加到emps_back表中
delimiter $
create trigger emps_insert_trigger
after insert on emps
for each row
begin
insert into emps_back(employee_id,last_name,salary)
values(new.employee_id,new.last_name,new.salary);
end $
delimiter ;
#4. 验证触发器是否起作用
insert into emps
values
(101,'wang',8000)
#5.创建触发器emps_del_trigger,每当向emps表中删除一条记录时,同步将删除的这条记录添加到 emps_back1表中,验证触发器是否起作用
delimiter $
create trigger emps_del_trigger
before delete on emps
for each row
begin
insert into emps_back(employee_id,last_name,salary)
values(OLD.employee_id,OLD.last_name,OLD.salary);
end $
delimiter ;