zoukankan      html  css  js  c++  java
  • MySQL之存储过程与触发器还有Event 事件

    PROCEDURE 存储过程

    存储过程:多表SQL的语句的集合,可以独立执行,存储过程保存在mysql.proc表中

    存储过程优势

    存储过程把经常使用的SQL语句或业务逻辑封装起来,预编译保存在数据库中,当需要时从数据库中直接调
    用,省去了编译的过程,提高了运行速度,同时降低网络数据传输量

    存储过程与自定义函数的区别
    存储过程实现的过程要复杂一些,而函数的针对性较强
    存储过程可以有多个返回值,而自定义函数只有一个返回值
    存储过程一般可独立执行,而函数往往是作为其他SQL语句的一部分来使用
    无参数的存储过程执行过程中可以不加(),函数必须加 ( )
    
    创建存储过程
    CREATE PROCEDURE sp_name ([ proc_parameter [,proc_parameter ...]])
    routime_body
    proc_parameter : [IN|OUT|INOUT] parameter_name type
    

    说明:其中IN表示输入参数,OUT表示输出参数,INOUT表示既可以输入也可以输出;param_name表
    示参数名称;type表示参数的类型

    查看存储过程列表
    SHOW PROCEDURE STATUS;
    

    查看存储过程定义

    SHOW CREATE PROCEDURE sp_name
    

    调用存储过程

    CALL sp_name ([ proc_parameter [,proc_parameter ...]])
    

    说明:当无参时,可以省略"()",当有参数时,不可省略"()"

    存储过程修改

    ALTER语句修改存储过程只能修改存储过程的注释等无关紧要的东西,不能修改存储过程体,所以要修改
    存储过程,方法就是删除重建

    删除存储过程
    DROP PROCEDURE [IF EXISTS] sp_name
    

    范例

    # 创建无参存储过程
    delimiter //
    CREATE PROCEDURE showTime()
    BEGIN
    SELECT now();
    END//
    delimiter ;
    CALL showTime;
    

    范例

    #创建含参存储过程:只有一个IN参数
    delimiter //
    CREATE PROCEDURE selectById(IN id SMALLINT UNSIGNED)
    BEGIN
        SELECT * FROM students WHERE stuid = id;
    END//
    delimiter ;
    call selectById(2);
    

    范例

    delimiter //
    CREATE PROCEDURE dorepeat(n INT)
    BEGIN
        SET @i = 0;
        SET @sum = 0;
        REPEAT SET @sum = @sum+@i;
        SET @i = @i + 1;
        UNTIL @i > n END REPEAT;
    END//
    delimiter ;
    CALL dorepeat(100);
    SELECT @sum;
    

    范例

    #创建含参存储过程:包含IN参数和OUT参数
    delimiter //
    CREATE PROCEDURE deleteById(IN id SMALLINT UNSIGNED, OUT num SMALLINT UNSIGNED)
    BEGIN
    DELETE FROM students WHERE stuid >= id;
    SELECT row_count() into num;
    END//
    delimiter ;
    call deleteById(20,@Line);
    SELECT @Line;
    #说明:创建存储过程deleteById,包含一个IN参数和一个OUT参数.调用时,传入删除的ID和保存被修改的行
    数值的用户变量@Line,select @Line;输出被影响行数
    #row_count() 系统内置函数,用于存放前一条SQL修改过的表的记录数
    
    流程控制

    存储过程和函数中可以使用流程控制来控制语句的执行

    IF:用来进行条件判断。根据是否满足条件,执行不同语句
    CASE:用来进行条件判断,可实现比IF语句更复杂的条件判断
    LOOP:重复执行特定的语句,实现一个简单的循环
    LEAVE:用于跳出循环控制,相当于SHELL中break
    ITERATE:跳出本次循环,然后直接进入下一次循环,相当于SHELL中continue
    REPEAT:有条件控制的循环语句。当满足特定条件时,就会跳出循环语句
    WHILE:有条件控制的循环语句
    

    TRIGGER 触发器

    触发器的执行不是由程序调用,也不是由手工启动,而是由事件来触发、激活从而实现执行

    创建触发器
    CREATE [DEFINER = { user | CURRENT_USER }]
        TRIGGER trigger_name
        trigger_time trigger_event
        ON tbl_name FOR EACH ROW
        trigger_body
    

    说明:
    trigger_name:触发器的名称

    trigger_time:{ BEFORE | AFTER },表示在事件之前或之后触发

    trigger_event::{ INSERT |UPDATE | DELETE},触发的具体事件

    tbl_name:该触发器作用在表名

    范例:

    #创建触发器,在向学生表INSERT数据时,学生数增加,DELETE学生时,学生数减少
    CREATE TABLE student_info (
    stu_id INT(11) NOT NULL AUTO_INCREMENT ,
    stu_name VARCHAR(255) DEFAULT NULL,
    PRIMARY KEY (stu_id)
    );
    CREATE TABLE student_count (
    student_count INT(11) DEFAULT 0
    );
    INSERT INTO student_count VALUES(0);
    CREATE TRIGGER trigger_student_count_insert
    AFTER INSERT
    ON student_info FOR EACH ROW
    UPDATE student_count SET student_count=student_count+1;
    CREATE TRIGGER trigger_student_count_delete
    AFTER DELETE
    ON student_info FOR EACH ROW
    UPDATE student_count SET student_count=student_count-1;
    
    [root@centos8 ~]#cat /var/lib/mysql/hellodb/trigger_student_count_delete.TRN
    TYPE=TRIGGERNAME
    trigger_table=student_info
    [root@centos8 ~]#cat /var/lib/mysql/hellodb/trigger_student_count_insert.TRN
    TYPE=TRIGGERNAME
    trigger_table=student_info
    [root@centos8 ~]#cat /var/lib/mysql/hellodb/student_info.TRG
    TYPE=TRIGGERS
    triggers='CREATE DEFINER=`root`@`localhost` TRIGGER
    trigger_student_count_insert
    AFTER INSERT
    ON student_info FOR EACH ROW
    UPDATE
    student_count SET student_count=student_count+1' 'CREATE
    DEFINER=`root`@`localhost` TRIGGER trigger_student_count_delete
    AFTER DELETE
    ON
    student_info FOR EACH ROW
    UPDATE student_count SET student_count=student_count-
    1'
    sql_modes=1411383296 1411383296
    definers='root@localhost' 'root@localhost'
    client_cs_names='utf8' 'utf8'
    connection_cl_names='utf8_general_ci' 'utf8_general_ci'
    db_cl_names='utf8_general_ci' 'utf8_general_ci'
    created=158207907828 158207907970
    
    查看触发器
    #在当前数据库对应的目录下,可以查看到新生成的相关文件:trigger_name.TRN,table_name.TRG
    SHOW TRIGGERS;
    #查询系统表information_schema.triggers的方式指定查询条件,查看指定的触发器信息。
    USE information_schema;
    SELECT * FROM triggers WHERE trigger_name='trigger_student_count_insert';
    
    删除触发器
    DROP TRIGGER trigger_name;
    

    Event 事件

    Event 事件介绍

    事件(event)是MySQL在相应的时刻调用的过程式数据库对象。一个事件可调用一次,也可周期性的
    启动,它由一个特定的线程来管理的,也就是所谓的"事件调度器"。
    事件和触发器类似,都是在某些事情发生的时候启动。当数据库上启动一条语句的时候,触发器就启动
    了,而事件是根据调度事件来启动的。由于它们彼此相似,所以事件也称为临时性触发器。
    事件取代了原先只能由操作系统的计划任务来执行的工作,而且MySQL的事件调度器可以精确到每秒钟
    执行一个任务,而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精确到每
    分钟执行一次
    
    事件的优缺点

    优点:一些对数据定时性操作不再依赖外部程序,而直接使用数据库本身提供的功能,可以实现每秒钟执行一个任务,这在一些对实时性要求较高的环境下就非常实用

    缺点:定时触发,不可以直接调用

    Event 管理

    相关变量和服务器选项

    MySQL事件调度器event_scheduler负责调用事件,它默认是关闭的。这个调度器不断地监视一个事件是否要调用,要创建事件,必须打开调度器

    服务器系统变量和服务器选项:

    event_scheduler:默认值为OFF,设置为ON才支持Event,并且系统自动打开专用的线程

    范例:开启和关闭event_scheduler

    #默认事件调度功能是关闭的
    MariaDB [(none)]> select @@event_scheduler;
    +-------------------+
    | @@event_scheduler |
    +-------------------+
    | OFF |
    +-------------------+
    1 row in set (0.000 sec)
    
    #临时开启事件调度功能
    MariaDB [(none)]> set global event_scheduler=1;
    Query OK, 0 rows affected (0.000 sec)
    
    #开启事件调度功能后,自启动一个event_scheduler线程
    MariaDB [(none)]> show processlist;
    
    #临时关闭事件调度功能
    MariaDB [(none)]> set global event_scheduler=0;
    Query OK, 0 rows affected (0.000 sec)
    
    MariaDB [(none)]> show processlist;
    
    #持久开启事件调度
    [root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
    [mysqld]
    event_scheduler=ON
    
    [root@centos8 ~]#systemctl restart mariadb
    

    管理事件

    create event 语句创建一个事件。每个事件由两个主要部分组成,第一部分是事件调度(event
    schedule),表示事件何时启动以及按什么频率启动,第二部分是事件动作(event action ),这是事
    件启动时执行的代码,事件的动作包含一条SQL语句,它可能是一个简单地insert或者update语句,也
    可以使一个存储过程或者 benin...end语句块,这两种情况允许我们执行多条SQL
    一个事件可以是活动(打开)的或停止(关闭)的,活动意味着事件调度器检查事件动作是否必须调
    用,停止意味着事件的声明存储在目录中,但调度器不会检查它是否应该调用。在一个事件创建之后,
    它立即变为活动的,一个活动的事件可以执行一次或者多次
    

    创建Event

    CREATE
        [DEFINER = { user | CURRENT_USER }]
        EVENT
        [IF NOT EXISTS]
        event_name
        ON SCHEDULE schedule
        [ON COMPLETION [NOT] PRESERVE]
        [ENABLE | DISABLE | DISABLE ON SLAVE]
        [COMMENT 'comment']
        DO event_body;
        
    schedule:
        AT timestamp [+ INTERVAL interval] ...
      | EVERY interval
        [STARTS timestamp [+ INTERVAL interval] ...]
        [ENDS timestamp [+ INTERVAL interval] ...]
        
    interval:
        quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
            WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
            DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}
    
    说明:
    event_name :创建的event名字,必须是唯一确定的
    ON SCHEDULE:计划任务
    schedule: 决定event的执行时间和频率(注意时间一定要是将来的时间,过去的时间会出错),有两种
    形式 AT和EVERY
    [ON COMPLETION [NOT] PRESERVE]: 可选项,默认是ON COMPLETION NOT PRESERVE 即计划任
    务执行完毕后自动drop该事件;ON COMPLETION PRESERVE则不会drop掉
    [COMMENT 'comment'] :可选项,comment 用来描述event;相当注释,最大长度64个字节
    [ENABLE | DISABLE] :设定event的状态,默认ENABLE:表示系统尝试执行这个事件, DISABLE:关
    闭该事情,可以用alter修改
    DO event_body: 需要执行的sql语句,可以是复合语句
    提示:event事件是存放在mysql.event表中
    

    查看Event

    SHOW EVENTS [{FROM | IN} schema_name]
        [LIKE 'pattern' | WHERE expr]
    

    注意:事件执行完即释放,如立即执行事件,执行完后,事件便自动删除,多次调用事件或等待执行事
    件,才可以用上述命令查看到。

    修改Event

    ALTER
        [DEFINER = { user | CURRENT_USER }]
        EVENT event_name
        [ON SCHEDULE schedule]
        [ON COMPLETION [NOT] PRESERVE]
        [RENAME TO new_event_name]
        [ENABLE | DISABLE | DISABLE ON SLAVE]
        [COMMENT 'comment']
        [DO event_body]
    

    注意:alter event语句可以修改事件的定义和属性。可以让一个事件成为停止的或者再次让它活动,也
    可以修改一个事件的名字或者整个调度。然而当一个使用 ON COMPLETION NOT PRESERVE 属性定义
    的事件最后一次执行后,事件直接就不存在了,不能修改

    删除Event

    DROP EVENT [IF EXISTS] event_name
    
    范例

    范例:创建立即启动事件

    MariaDB [(none)]> create database testdb;
    Query OK, 1 row affected (0.000 sec)
    MariaDB [(none)]> use testdb;
    Database changed
    #创建一个表记录每次事件调度的名字和事件戳
    MariaDB [testdb]> create table events_list(event_name varchar(20) not null,
    event_started timestamp not null);
    Query OK, 0 rows affected (0.005 sec)
    #临时关闭事件调度功能
    MariaDB [testdb]> set global event_scheduler=0;
    Query OK, 0 rows affected (0.000 sec)
    MariaDB [testdb]> show variables like 'event_scheduler';
    +-----------------+-------+
    | Variable_name | Value |
    +-----------------+-------+
    | event_scheduler | OFF |
    +-----------------+-------+
    1 row in set (0.001 sec)
    #创建一次性事件
    MariaDB [testdb]> create event event_now on schedule at now() do insert
    into events_list values('event_now', now());
    Query OK, 0 rows affected (0.001 sec)
    #因为事件调度功能禁用,所有表中无记录
    MariaDB [testdb]> select * from events_list;
    Empty set (0.000 sec)
    #查看事件
    MariaDB [test]> show eventsG;
    
    #任务计划存放在mysql.event表中
    MariaDB [testdb]> select * from mysql.eventG;
    *************************** 1. row ***************************
    db: testdb
    name: event_now
    body: insert into events_list values('event_now', now())
    definer: root@localhost
    execute_at: 2020-02-19 02:46:04
    interval_value: NULL
    interval_field: NULL
    created: 2020-02-19 10:46:04
    modified: 2020-02-19 10:46:04
    last_executed: NULL
    starts: NULL
    ends: NULL
    status: ENABLED
    on_completion: DROP
    sql_mode:
    STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUB
    STITUTION
    comment:
    originator: 1
    time_zone: SYSTEM
    character_set_client: utf8
    collation_connection: utf8_general_ci
    db_collation: latin1_swedish_ci
    body_utf8: insert into events_list values('event_now', now())
    1 row in set (0.000 sec)
    
    #开启事件调度功能
    MariaDB [testdb]> set global event_scheduler=1;
    Query OK, 0 rows affected (0.000 sec)
    #事件立即执行,每秒插入一条记录
    MariaDB [testdb]> select * from events_list;
    +------------+---------------------+
    | event_name | event_started |
    +------------+---------------------+
    | event_now | 2019-12-02 22:07:11 |
    +------------+---------------------+
    1 row in set (0.001 sec)
    #事件执行完成后自动删除
    MariaDB [testdb]> show events;
    Empty set (0.001 sec)
    

    范例:创建每秒启动的事件

    MariaDB [testdb]> CREATE EVENT event_every_second ON SCHEDULE EVERY 1 SECOND
    DO INSERT INTO events_list VALUES('event_now', now());
    MariaDB [testdb]> SHOW EVENTSG;
    *************************** 1. row ***************************
    Db: testdb
    Name: event_every_second
    Definer: root@localhost
    Time zone: SYSTEM
    Type: RECURRING
    Execute at: NULL
    Interval value: 1
    Interval field: SECOND
    Starts: 2019-12-02 22:26:52
    Ends: NULL
    Status: ENABLED
    Originator: 1
    character_set_client: utf8
    collation_connection: utf8_general_ci
    Database Collation: latin1_swedish_ci
    1 row in set (0.002 sec)
    
    #事件是存放在mysql.event表中
    MariaDB [testdb]> select * from mysql.eventG;
    
    MariaDB [testdb]> select *from events_list;
    
    MariaDB [testdb]> drop event event_every_second;
    Query OK, 0 rows affected (0.000 sec)
    MariaDB [testdb]> SHOW EVENTSG
    Empty set (0.001 sec)
    MariaDB [testdb]> select * from mysql.eventG
    Empty set (0.000 sec)
    
  • 相关阅读:
    DPDK — 网卡初始化流程(Intel 82599 ixgbe 网卡驱动示例)
    leetcode 3. 无重复字符的最长子串
    20193120 实验四 Python综合实践
    hadoop常用的端口号
    Django学习笔记
    ORACLE EBS AP invoice 到付款的数据流
    EBS 系统标准职责定义MAP
    Advanced Pricing
    Oracle Advanced Pricing White Papers
    增加AP INVOICE 行&分配行
  • 原文地址:https://www.cnblogs.com/xuanlv-0413/p/14778689.html
Copyright © 2011-2022 走看看