DROP PROCEDURE IF EXISTS pro_test2; delimiter $$ CREATE PROCEDURE pro_test2 () BEGIN DECLARE no_more_record INT DEFAULT 0 ; DECLARE stubirth_year INT ; DECLARE stu_id INT ; DECLARE stu_birth VARCHAR (10) ; DECLARE cursor_test CURSOR FOR SELECT stuid, stubirth FROM tb_student3 ; /*首先这里对游标进行定义*/ DECLARE CONTINUE HANDLER FOR NOT found SET no_more_record = 1 ; /*这个是个条件处理,针对NOT FOUND的条件,当没有记录时赋值为1*/ OPEN cursor_test ; /*接着使用OPEN打开游标*/ -- 开始循环 read_loop : LOOP -- 提取游标里的数据,这里只有一个,多个的话也一样; FETCH cursor_test INTO stu_id, stu_birth ; /*把第一行数据写入变量中,游标也随之指向了记录的第一行*/ -- 声明结束的时候 SET stubirth_year = CONVERT ( SUBSTRING_INDEX(stu_birth, '-', 1), SIGNED ) ; /*截取年份*/ -- 注意:这里的循环体可以根据自己的需要设定(while,while...do,if...then等等) IF no_more_record = 1 THEN LEAVE read_loop ; END IF ; -- 这里做你想做的循环的事件 IF stubirth_year > 1990 AND stubirth_year < 2000 THEN UPDATE tb_student3 SET comments = '90后' WHERE stuid = stu_id ; ELSEIF stubirth_year > 1980 AND stubirth_year < 1990 THEN UPDATE tb_student3 SET comments = '80后' WHERE stuid = stu_id ; ELSEIF stubirth_year > 1970 AND stubirth_year < 1980 THEN UPDATE tb_student3 SET comments = '70后' WHERE stuid = stu_id ; ELSE UPDATE tb_student3 SET comments = '有问题' WHERE stuid = stu_id ; END IF ; END LOOP read_loop ; CLOSE cursor_test ; /*用完后记得用CLOSE把资源释放掉*/ END$$ delimiter ;create trigger语句 • create trigger语句用来创建一个触发器,触发器的作用是当表上 有对应SQL语句发生时,则触发执行 • 触发器创建时需要指定对应的表名tbl_name
CREATE [DEFINER = user] TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW [trigger_order] trigger_body trigger_time: { BEFORE | AFTER } trigger_event: { INSERT | UPDATE | DELETE } trigger_order: { FOLLOWS | PRECEDES } other_trigger_name• Definer关键词用来指定trigger的安全环境 • Trigger_time指定触发器的执行时间,BEFORE和AFTER指定触发器在表中的每行数据修改前或者后执行 • Trigger_event指定触发该触发器的具体事件 • INSERT当新的一行数据插入表中时触发,比如通过执行insert,loaddata,replace语句插入新数据 • UPDATE当表的一行数据被修改时触发,比如执行update语句时 • DELETE当表的一行数据被删除时触发,比如执行delete,replace语句时 • 当执行insert into … on duplicate key update语句时,当碰到重复行执行update时,则触发update下的触发器 • 从5.7.2版本开始,可以创建具有相同trigger_time和trigger_event的同一个表上的多个触发器,默认情况下按照创建的时间依次执行,通过指定FOLLOWS/PRECEDES改变执行顺序,即FOLLOWS时表示新创建的触发器后执行,PRECEDES则表示新触发器先执行 • Trigger_body表示触发器触发之后要执行的一个或多个语句,在内部可以引用涉及表的字段,OLD.col_name表示行数据被修改或删除之前的字段数据,NEW.col_name表示行数据被插入或修改之后的字段数据
drop TRIGGER if EXISTS simple_trigger; delimiter// create TRIGGER simple_trigger AFTER UPDATE on teacher for EACH ROW BEGIN insert into h_teacher(tno,new_tname,old_tname,sdate) VALUES(new.tno,new.tname,old.tname,now()); END; // delimiter ;
mysql> select * from teacher ; +------+--------+ | tno | tname | +------+--------+ | t001 | 刘冬 | | t002 | 刘冬 | | t003 | 刘冬 | | t004 | 刘冬 | | t005 | 刘冬 | +------+--------+ 5 rows in set (0.00 sec) mysql> select * from h_teacher ; Empty set (0.01 sec) mysql> update teacher set tname='刘冬2' where tno='t001'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from h_teacher ; +------+-----------+-----------+---------------------+ | tno | new_tname | old_tname | sdate | +------+-----------+-----------+---------------------+ | t001 | 刘冬2 | 刘冬 | 2021-05-03 10:56:45 | +------+-----------+-----------+---------------------+ 1 row in set (0.00 sec) mysql>
触发器实现的效果,在程序中也能实现,更多的是放在程序中实现,比如写了触发器后期没用维护给忘了,会出现些难排查的场景。
比如程序员不知道有触发器的话,就不会想到主键冲突的原因了。
mysql> show create table teacher; +---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | teacher | CREATE TABLE `teacher` ( `tno` varchar(10) COLLATE utf8_bin NOT NULL, `tname` varchar(20) COLLATE utf8_bin DEFAULT NULL, PRIMARY KEY (`tno`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin | +---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) mysql> update teacher set tname='刘冬2' where tno='t001'; ERROR 1062 (23000): Duplicate entry 't001' for key 'PRIMARY' mysql>
注意事项:比如上面的执行update操作时,与触发器是在同一个事务内的。