diff --git "a/20 \347\237\263\350\211\257\346\266\233/20231011 \346\270\270\346\240\207\344\270\216\345\255\230\345\202\250\350\277\207\347\250\213.md" "b/20 \347\237\263\350\211\257\346\266\233/20231011 \346\270\270\346\240\207\344\270\216\345\255\230\345\202\250\350\277\207\347\250\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..50ea946c5ecce81db775636e86296cc2dceb698d --- /dev/null +++ "b/20 \347\237\263\350\211\257\346\266\233/20231011 \346\270\270\346\240\207\344\270\216\345\255\230\345\202\250\350\277\207\347\250\213.md" @@ -0,0 +1,121 @@ +### 笔记 + +#### 存储函数 + +函数是有返回值的 + +跟存储过程一样都要有定界符 + +函数返回值只能返回一个 + +###### 语法 + +~~~mysql +delimiter // +create function 函数名() # function 没有其他参数类型只有一个in 但是不要写in +returns (结束的数据类型) +deterministic +#如果是sql 语句就需要写 +contains sql +# 如果不是sql语句则是 +contains nosql +begin + return (要返回的结果) # 一般是sql语句 只有一行一列的结果 但也可以是精确的摸一个值 +end // +delimiter ; +#查看存储函数 +select 函数名; +~~~ + +##### 游标 + +每次只处理一行,逐行处理 + +游标需要在begin + +~~~mysql +1. 声明游标 +declare 游标名 cursor for sql语句 +2. 打开游标 +open 游标名 +3. 使用游标 +fetch 游标名 into 变量1,变量....N +4. 关闭游标 +close 游标名 +~~~ + + + +### 作业 + +~~~mysql +-- -- 部门表 + create database maidui charset utf8; + use maidui; + create table dept( + deptno int primary key auto_increment, -- 部门编号 + dname varchar(14) , -- 部门名字 + loc varchar(13) -- 地址 + ) ; + -- 员工表 + create table emp( + empno int primary key auto_increment,-- 员工编号 + ename varchar(10), -- 员工姓名 - + job varchar(9), -- 岗位 + mgr int, -- 直接领导编号 + hiredate date, -- 雇佣日期,入职日期 + sal int, -- 薪水 + comm int, -- 提成 + deptno int not null, -- 部门编号 + foreign key (deptno) references dept(deptno) + ); + insert into dept values(10,'财务部','北京'); + insert into dept values(20,'研发部','上海'); + insert into dept values(30,'销售部','广州'); + insert into dept values(40,'行政部','深圳'); + insert into emp values(7369,'刘一','职员',7902,'1980-12-17',800,null,20); + insert into emp values(7499,'陈二','推销员',7698,'1981-02-20',1600,300,30); + insert into emp values(7521,'张三','推销员',7698,'1981-02-22',1250,500,30); + insert into emp values(7566,'李四','经理',7839,'1981-04-02',2975,null,20); + insert into emp values(7654,'王五','推销员',7698,'1981-09-28',1250,1400,30); + insert into emp values(7698,'赵六','经理',7839,'1981-05-01',2850,null,30); + insert into emp values(7782,'孙七','经理',7839,'1981-06-09',2450,null,10); + insert into emp values(7788,'周八','分析师',7566,'1987-06-13',3000,null,20); + insert into emp values(7839,'吴九','总裁',null,'1981-11-17',5000,null,10); + insert into emp values(7844,'郑十','推销员',7698,'1981-09-08',1500,0,30); + insert into emp values(7876,'郭十一','职员',7788,'1987-06-13',1100,null,20); + insert into emp values(7900,'钱多多','职员',7698,'1981-12-03',950,null,30); + insert into emp values(7902,'大锦鲤','分析师',7566,'1981-12-03',3000,null,20); + insert into emp values(7934,'木有钱','职员',7782,'1983-01-23',1300,null,10); + + +-- 2.利用游标修改表格,如果sal<1000,则删除工资为此值的员工,如果1000 < sal <= 3000,该员工薪资涨100并将该员工的信息放在新表中,否则扣工资100 +drop procedure youbiao; +delimiter // +create procedure youbiao() +begin + declare id int; + declare nsal int; + declare i int default 1; + declare num1 cursor for select empno,sal from emp; + declare continue handler for 1329 set i=2; + open num1; + create table if not exists xinbiao( + empno int primary key auto_increment,-- 员工编号 + sal int -- 薪水 + ); + while i=1 do + fetch num1 into id,nsal; + if nsal<1000 then delete from emp where empno=id; + elseif 1000=3000 then update emp set sal=sal+100 where empno=id; + insert into xinbiao values(id,nsal); + else update emp set sal=sal-100 where empno=id; + end if; + end while; + close num1; +end // +delimiter ; +call II(); +select * from xinbiao; +~~~ + diff --git "a/20 \347\237\263\350\211\257\346\266\233/20231012 \350\247\246\345\217\221\345\231\250.md" "b/20 \347\237\263\350\211\257\346\266\233/20231012 \350\247\246\345\217\221\345\231\250.md" new file mode 100644 index 0000000000000000000000000000000000000000..8070f91389af13b2e9adc1fe8e5c953d7d719628 --- /dev/null +++ "b/20 \347\237\263\350\211\257\346\266\233/20231012 \350\247\246\345\217\221\345\231\250.md" @@ -0,0 +1,152 @@ +# 触发器 + +触发器(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) +~~~ \ No newline at end of file