目录
一. MySQL事件Event
二. MySQL触发器trigger
三. MySQL存储过程Stored Procedure
四. MySQL临时表
1. 事件简介
事件(event)是MySQL在相应的时刻调用的过程式数据库对象。一个事件可调用一次,也可周期性的启动,它由一个特定的线程来管理的,也就是所谓的“事件调度器”。
事件和触发器类似,都是在某些事情发生的时候启动。当数据库上启动一条语句的时候,触发器就启动了,而事件是根据调度事件来启动的。由于他们彼此相似,所以事件也称为临时性触发器。
事件取代了原先只能由操作系统的计划任务来执行的工作,而且MySQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精确到每分钟执行一次。
2. 事件的优缺点
2.1 优点
一些对数据定时性操作不再依赖外部程序,而直接使用数据库本身提供的功能。
可以实现每秒钟执行一个任务,这在一些对实时性要求较高的环境下就非常实用了。
2.2 缺点
定时触发,不可以调用。
3. 创建事件
一条create event语句创建一个事件。每个事件由两个主要部分组成。
第一部分是事件调度(event schedule),表示事件何时启动以及按什么频率启动。
第二部分是事件动作(event action ),这是事件启动时执行的代码。
事件的动作包含一条SQL语句,它可能是一个简单地insert或者update语句,也可以使一个存储过程或者 benin...end语句块,这两种情况允许我们执行多条SQL。
一个事件可以是活动(打开)的或停止(关闭)的,活动意味着事件调度器检查事件动作是否必须调用,停止意味着事件的声明存储在目录中,但调度器不会检查它是否应该调用。在一个事件创建之后,它立即变为活动的,一个活动的事件可以执行一次或者多次。
3.1 创建语法如下
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语句(可以是复合语句)。CREATE EVENT在存储过程中使用时合法的。
3.2 开启关闭事件调度器
3.2.1 MySQL事件调度器event_scheduler负责调用事件,它默认是关闭的。这个调度器不断地监视一个事件是否要调用, 要创建事件,必须打开调度器。
mysql> show variables like '%event_scheduler%';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| event_scheduler | OFF |
+-----------------+-------+
3.2.2 开启事件调度器
通过命令行 可通过如下任何一个命令行 重启mysql后恢复,事件不执行,重新设置
SET GLOBAL event_scheduler = ON;
SET @@global.event_scheduler = ON;
SET GLOBAL event_scheduler = 1;
SET @@global.event_scheduler = 1;
通过配置文件my.cnf
event_scheduler = 1 #或者ON
3.2.3查看调度器线程
mysql> show processlist;
+----+-----------------+-----------+------+---------+------+------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------+---------+------+------------------------+------------------+
| 2 | root | localhost | NULL | Query | 0 | NULL | show processlist |
| 3 | event_scheduler | localhost | NULL | Daemon | 6 | Waiting on empty queue | NULL |
+----+-----------------+-----------+------+---------+------+------------------------+------------------+
3.2.4 关闭事件调度器
通过命令行 可通过如下任何一个命令行
SET GLOBAL event_scheduler = OFF;
SET @@global.event_scheduler = OFF;
SET GLOBAL event_scheduler = 0;
SET @@global.event_scheduler = 0;
通过配置文件my.cnf
event_scheduler = 0 #或者OFF,DISABLED
3.3 创建
3.3.1 立即启动事件
create event event_now on schedule every 1 second do INSERT INTO event_list values('', now(), '111');
3.3.2 每秒钟调用存储过程
CREATE DEFINER=`root`@`localhost` EVENT `eventUpdateStatus` ON SCHEDULE EVERY 1 SECOND STARTS '2017-11-21 00:12:44' ON COMPLETION PRESERVE ENABLE DO call updateStatus()
4. 查看事件
查看当前所在库的事件mysql> show events;
查看所有事件mysql> select * from mysql.event;
5. 修改事件
一条alter event语句可以修改事件的定义和属性。我们可以让一个事件成为停止的或者再次让它活动,也可以修改一个事件的名字或者整个调度。然而当一个使用 ON COMPLETION NOT PRESERVE 属性定义的事件最后一次执行后,事件直接就不存在了,不能修改。
5.1 语法如下:
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]
6.删除事件
如果一个事件不再需要,我们可以使用一条drop event 语句删除它。使用这条语句我们不需要等到最后一次事件调用。
6.1 基本语法DROP EVENT [IF EXISTS] event_name;
1. 触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。
2. 触发器的特性:
1、有begin end体,begin end;之间的语句可以写的简单或者复杂
2、什么条件会触发:I、D、U
3、什么时候触发:在增删改前或者后
4、触发频率:针对每一行执行
5、触发器定义在表上,附着在表上。
触发器尽量少的使用,因为不管如何,它还是很消耗资源,如果使用的话要谨慎的使用,确定它是非常高效的:触发器是针对每一行的;对增删改非常频繁的表上切记不要使用触发器,因为它会非常消耗资源。
3. 创建触发器
CREATE
[DEFINER = { user | CURRENT_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
BEFORE和AFTER参数指定了触发执行的时间,在事件之前或是之后。
FOR EACH ROW表示任何一条记录上的操作满足触发事件都会触发该触发器,也就是说触发器的触发频率是针对每一行数据触发一次。
4. tigger_event详解:
INSERT型触发器:插入某一行时激活触发器,可能通过INSERT、LOAD DATA、REPLACE 语句触发(LOAD DAT语句用于将一个文件装入到一个数据表中,相当与一系列的INSERT操作);
UPDATE型触发器:更改某一行时激活触发器,可能通过UPDATE语句触发;
DELETE型触发器:删除某一行时激活触发器,可能通过DELETE、REPLACE语句触发。
trigger_order是MySQL5.7之后的一个功能,用于定义多个触发器,使用follows(尾随)或precedes(在…之先)来选择触发器执行的先后顺序。
5. 创建只有一个执行语句的触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件 ON 表名 FOR EACH ROW 执行语句;
CREATE TRIGGER event_list_insert BEFORE INSERT ON event_list
FOR EACH ROW
insert into trigger_list values('', NOW(), NEW.time);
创建有多个执行语句的触发器
CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW
BEGIN
执行语句列表
END;
6. NEW与OLD详解
MySQL 中定义了 NEW 和 OLD,用来表示触发器的所在表中,触发了触发器的那一行数据,来引用触发器中发生变化的记录内容,具体地:
在INSERT型触发器中,NEW用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
在UPDATE型触发器中,OLD用来表示将要或已经被修改的原数据,NEW用来表示将要或已经修改为的新数据;
在DELETE型触发器中,OLD用来表示将要或已经被删除的原数据;
使用方法:
NEW.columnName (columnName为相应数据表某一列名)
另外,OLD是只读的,而NEW则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用。
7. 查看触发器
7.1 SHOW TRIGGERS语句查看触发器信息
mysql> SHOW TRIGGERS;
结果,显示所有触发器的基本信息;无法查询指定的触发器。
7.2 在information_schema.triggers表中查看触发器信息
mysql> SELECT * FROM information_schema.triggers;
7.3 除触发器
DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name
如果不需要某个触发器时一定要将这个触发器删除,以免造成意外操作,
1. 存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象。
1.1 优点
存储过程可封装,并隐藏复杂的商业逻辑。
存储过程可以回传值,并可以接受参数。
存储过程无法使用 SELECT 指令来运行,因为它是子程序,与查看表,数据表或用户定义函数不同。
存储过程可以用在数据检验,强制实行商业逻辑等。
1.2 缺点
存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
存储过程的性能调校与撰写,受限于各种数据库系统。
2. 创建存储过程
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
proc_parameter:
[ IN | OUT | INOUT ] param_name type
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
routine_body:
Valid SQL routine statement
[begin_label:] BEGIN
[statement_list]
……
END [end_label]
3. MYSQL 存储过程中的关键语法
声明语句结束符,可以自定义:
DELIMITER $$ 或 DELIMITER //
使用 DELIMITER \$\$ 命令将语句的结束符号从分号 ; 临时改为两个 \$\$,
使得过程体中使用的分号被直接传递到服务器,而不会被客户端(如mysql)解释。
声明存储过程:
CREATE PROCEDURE demo_in_parameter(IN p_in int)
存储过程开始和结束符号:
BEGIN .... END
变量赋值:
SET @p_in=1
变量定义:
DECLARE l_int int unsigned default 4000000;
创建mysql存储过程、存储函数:
create procedure 存储过程名(参数)
存储过程体:
create function 存储函数名(参数)
调用:
call sp_name[(传参)];
4. 查看存储过程
SHOW PROCEDURE STATUS [where db='数据库名'];
SELECT * FROM mysql.proc;
show create procedure 数据库.存储过程名
select name from mysql.proc where db='数据库名';
5. 修改、删除存储过程
ALTER PROCEDURE;
DROP PROCEDURE 存储过程名;
6. 存储过程的参数
三种参数类型 IN OUT INOUT
CREATE PROCEDURE 存储过程名([[IN |OUT |INOUT ] 参数名 数据类形...])
IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)
OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)
确保参数的名字不等于列的名字,否则在过程体中,参数名被当做列名来处理
7. 变量
7.1 定义变量
DECLARE variable_name [,variable_name...] datatype [DEFAULT value];
datatype -> int, float, date,varchar(length)
Eg: DECLARE int1 int unsigned default 1;
7.2 变量赋值
SET 变量名 = 表达式值 [,variable_name = expression ...]
7.3用户变量
用户变量名一般以@开头
滥用用户变量会导致程序难以理解及管理
CREATE PROCEDURE GreetWorld( ) SELECT CONCAT(@greeting,' World');
mysql > SET @greeting='Hello';
mysql > CALL GreetWorld( ); -> Hello World
8. 控制语句
8.1 变量作用域
内部的变量优先,对外不可见。
8.2 条件语句
8.2.1 if语句
if 条件 then
语句
else
语句
end if;
8.2.2 case语句
case 变量
when 期望值1 then
语句
when 期望值2 then
语句
else
语句
end case;
case
when var=0 then
insert into t values(30);
when var>0 then
when var<0 then
else
end case;
8.2.3 循环
while 条件 do
--循环体
end while;
repeat
--循环体
until 循环条件
end repeat;
loop 循环不需要初始条件,这点和 while 循环相似,同时和 repeat 循环一样不需要结束条件, leave 语句的意义是离开循环。
LOOP_LABLE:loop
语句
leave LOOP_LABLE; --if var>2 then leave LOOP_LABLE; end if;
语句
end loop;
8.2.4 LABLES 标号:
标号可以用在 begin repeat while 或者 loop 语句前,语句标号只能在合法的语句前面使用。可以跳出循环,使运行指令达到复合语句的最后一步。
8.2.5 ITERATE迭代
ITERATE 通过引用复合语句的标号,来从新开始复合语句
LOOP_LABLE:loop
语句
ITERATE LOOP_LABLE; --if var>2 then ITERATE LOOP_LABLE; end if;
语句
leave LOOP_LABLE; --if var>2 then leave LOOP_LABLE; end if;
语句
end loop;
9. 实例
delimiter $$
create procedure procedure_list_delete(in list_id integer)
begin
delete from procedure_list where id = list_id;
end$$
delimiter ;
调用
call procedure_list_delete(1);
临时表:表建在内存里,数据在内存里 临时表主要是为了放一些中间结果集
内存表:表建在磁盘里,数据在内存里 存储引擎为MEMORY
MySQL 临时表在我们需要保存一些临时数据时是非常有用的。临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。每当PHP脚本执行完成后,该临时表也会自动销毁。MySQL客户端程序连接MySQL数据库服务器来创建临时表,那么只有在关闭客户端程序时才会销毁临时表,也可以手动销毁。临时表默认的是Mysql指定的默认Engine。
SHOW TABLES不可见,SHOW CREATE TABLE 表名可见。
1. 建表
create temporary table 表名;
drop table 表名;
create temporary table tests(id VARCHAR(50) NOT NULL);