diff --git "a/04 \346\235\216\346\230\216\345\201\245/20231012 \350\247\246\345\217\221\345\231\250.md" "b/04 \346\235\216\346\230\216\345\201\245/20231012 \350\247\246\345\217\221\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..56fb4f32f6c399b0722967756242f75419bb5370 --- /dev/null +++ "b/04 \346\235\216\346\230\216\345\201\245/20231012 \350\247\246\345\217\221\345\231\250.md" @@ -0,0 +1,153 @@ +# 触发器 + +触发器(trigger)是与表有关的数据库对象,指在insert/update/delete之前(BEFORE)或之后(AFTER),触发并执行触发器中定义的SQL语句集合。 + +事件A 对user表新增一条数据 姓名name 年龄age 性别sex + +事件B 对userlogs记录一条user表的操作 new.name,new.age + + + +触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作。 + +使用别名OLD和NEW来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。**触发器只支持行级触发** + + + +### 触发器的类型 + +| 类型 | NEW和OLD | +| ------ | ---------------------------------------- | +| insert | new代表将要新增或已新增的数据 | +| update | old代表更新前的数据、new代表更新后的数据 | +| delete | old代表将要删除或已删除的数据 | + + + +### 语法 + +创建触发器 + +```sql +create trigger 触发器名称 +before/after(触发时机) insert/update/delete(触发类型) +on 表名 for each row -- 行级触发器 +begin + 触发的语句... +end; +``` + +查看 + +```sql +show triggers; +``` + +删除 + +```sql +drop trigger 触发器名称; +``` + +### 案例 + +通过触发器记录 tb_user 表的数据变更日志,将变更日志插入到日志表user_logs中, 包含增、删、改 ; + +user_logs表结构 + +```sql +create table user_logs( + id int(11) primary key auto_increment, + operation varchar(20) not null comment '操作类型, insert/update/delete', + operate_time datetime not null comment '操作时间', + operate_id int(11) not null comment '操作的ID', + operate_params varchar(500) comment '操作参数' +) +``` + +A.插入数据触发器 + +B.更新数据触发器 + +C.删除数据触发器 + +**自己定义错误代码**: + +~~~ mysql +signal sqlstate 'MD001' set message_text = '行数超出5行,不能新增'; +~~~ + + + +### 练习 + +模拟一个食品库存表,当食品采购时,记录采购信息并更改库存。 + +##### 食品存表 (Food): + +food_id: 食品ID (主键) +food_name: 食品名称 +quantity: 食品数量 + +##### 食品采购记录表 (DeliveryLog): + +log_id: 采购记录ID (主键) +food_id: 食品ID (外键) +quantity: 采购数量 +delivery_date: 采购日期 + +~~~mysql +create database test02 charset utf8; +use test02; + + + +-- 食品库存表 (Food): +create table food( + food_id int primary key auto_increment, -- 食品ID (主键) + food_name varchar(10), -- 食品名称 + quantity int -- 食品数量 +); +insert into food values +(null,'手撕面包',90), +(null,'老坛酸菜牛肉面',40), +(null,'虎皮凤爪',30), +(null,'矿泉水',20), +(null,'牛肉干',50); + +-- 食品采购记录表 (DeliveryLog): +create table delivery_log( + log_id int primary key auto_increment, -- 采购记录ID (主键) + food_id int, -- 食品ID + quantity int, -- 采购数量 + delivery_date date, -- 采购日期 + foreign key (food_id) references food(food_id) -- (外键) +); + +-- 模拟一个食品库存表,当食品采购时,记录采购信息并更改库存。 + +# 定义一个用户采购存储过程 +delimiter $$ +create procedure buy(in buy_food varchar(20),in num int) +begin + update food set quantity = quantity - num where food_name = buy_food; +end $$ +delimiter ; + +# 定义一个触发器 +delimiter $$ +create trigger text_buy +after update on food +for each row +begin + select food_id into @id from food where food_name = @food; + insert into delivery_log values(null,@id,@num,now()); +end $$ +delimiter ; + +set @food = '虎皮凤爪'; +set @num = 28; +set @id = null; +call buy(@food,@num) +~~~ +