zoukankan      html  css  js  c++  java
  • mysql8学习笔记21--游标触发器

    cursor游标
    • Cursor游标用来声明一个数据集
    • 游标的声明必须在变量和条件声明之后,在handler声明之前
    • Cursor close语句用来关闭之前打开的游标

    • 如果关闭一个未打开的游标,则MySQL会报错
    • 如果在存储过程和函数中未使用此语句关闭已经打开的游标,则游标会在声
    明的begin…end语句块执行完之后自动关闭
    • Cursor declare语句用来声明一个游标和指定游标对应的数据集合,通常数据
    集合是一个select语句

    • Select_statement代表一个select语句
    • Cursor fetch语句用来获取游标指定数据集的下一行数据并将各个字段值赋予
    后面的变量
    • 数据集中的字段需要和INTO语句中定义的变量一一对应
    • 数据集中的数据都fetch完之后,则返回NOT FOUND
    • Open cursor语句用来打开一个之前已经声明好的游标

    以下是游标例子:

    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操作时,与触发器是在同一个事务内的。

     查看创建的触发器

     

     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    深度学习
    !gcc !vi
    条件、循环及其他语句
    当索引行不通时
    我的排班日期
    Linux使用storcli工具查看服务器硬盘和raid组信息
    storcli64和smartctl定位硬盘的故障信息
    Shell-四剑客
    iostat
    /VAR/LOG/各个日志文件分析
  • 原文地址:https://www.cnblogs.com/laonicc/p/14016259.html
Copyright © 2011-2022 走看看