mysql数据库应用fileapi.it.hactcm.edu.cn › mysql › file › 2020 › 5 › 22 ›...

50
MySQL数据库应用 河南中医药大学信息技术学院 王昂 2019.02

Upload: others

Post on 30-Jun-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

MySQL数据库应用

河南中医药大学信息技术学院 王昂

2019.02

Page 2: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 2 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

第六章 MySQL过程式数据库对象

主讲内容:存储过程、存储函数、触发器、事件

Page 3: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 3 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

教学内容

1. 存储过程

2. 存储函数

3. 触发器

4. 事件

Page 4: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 4 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

一条select……into语句返回的是带有值的一行,这样可以把数据读

取到存储过程中,但是常规的select查询语句可以返回多行记录,如果

数据量非常大,这就需要在存储过程中使用游标来逐条读取查询结果集

中的数据。

使用游标需要用到4条特殊语句,分别是:

− DECLARE CURSOR(声明游标)

− OPEN CURSOR(打开游标)

− FETCH CURSOR(读取游标)

− CLOSE CURSOR(关闭游标)

Page 5: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 5 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

(1)声明游标 语法格式:

DECLARE 游标名 CURSOR FOR select语句

说明:

- 游标只能在存储过程或存储函数中使用。

- 一个块中的每一个游标必须有唯一的名字。

- 上述SELECT语句不能有INTO子句。

Page 6: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 6 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

下面的定义符合一个游标声明:

declare xs_cur1 cursor for select 学号,姓名,性别,出生日期,总学分 from xs where 专业名 = '计算机';

Page 7: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 7 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

(2)打开游标

声明游标后,要使用游标从中提取数据,就必须先打开游标。

使用OPEN语句打开游标,其格式为:

OPEN 游标名

例如:打开游标xs_cur1。

open xs_cur1

Page 8: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 8 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

(3)读取数据

游标打开后,就可以使用FETCH…INTO语句从中读取数据。

语法格式:

FETCH 游标名 INTO 变量名 ...

说明:

- FETCH ...INTO语句与SELECT...INTO语句具有相同的意义;

- FETCH语句是将游标指向的一行数据赋给一些变量, FETCH子句中变量

的数目必须等于声明游标时SELECT子句中列的数目。

将查询到的数据存储在变量中,因此需要读取刚才打开过的游标:

fetch xs_cur1 into xh,xm,xb,csrq,zxf;

Page 9: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 9 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

(4)关闭游标

游标使用完以后,要及时关闭。关闭游标使用CLOSE语句。

语法格式为:

CLOSE 游标名

例如:关闭游标xs_cur1。

CLOSE xs_cur1

Page 10: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 10 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.1.3游标及其应用

【例6.9】创建一个存储过程,计算xs表中行的数目。 delimiter $$ create procedure compute(out number integer) begin declare xh char(6); declare found boolean default true; declare number_xs cursor for select 学号 from xs; declare continue handler for not found set found=false; set number=0; open number_xs; fetch number_xs into xh; while found do set number=number+1; fetch number_xs into xh; end while; close number_xs; end$$ delimiter ; call compute(@num); select @num;

number_xs :游标名

Page 11: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 11 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2 存储函数

存储函数也是过程式对象乊一,创建存储函数与存储过程大致相同。 1.创建存储函数CREATE FUNCTION 语法格式: CREATE FUNCTION 存储过程名 ([参数 ... ]) RETURNS type [特征 ...] 存储函数体 说明:

- 存储函数不能拥有与存储过程相同的名字。

- 存储函数的参数只有名称和类型,不能指定IN、OUT和INOUT。

- RETURNS type子句声明函数返回值的数据类型。

- 存储函数体:存储函数体中必须包含一个RETURN value语句。

Page 12: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 12 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.1 创建存储函数

【例6.15】创建一个存储函数,它返回xs表中学生的数目作为结果。 delimiter $$ create function num_of_xs( ) returns integer begin return (select count(*) from xs); end$$ delimiter ; 说明:RETURN子句中包含SELECT语句时,SELECT语句的返回结果只能

是一行且只能有一列值。

Page 13: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 13 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.1 创建存储函数

【例6.16】创建一个存储函数,返回某个学生的姓名。 delimiter $$ create function name_of_stu(xh char(6)) returns char(8) begin return (select 姓名 from xs where 学号=xh); end$$ delimiter ;

Page 14: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 14 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.1 创建存储函数

【例6.17】创建一个存储函数来删除xs_kc表中有,但xs表中丌存在的学号。如果调用存储函数时,参数中的学号在xs表中丌存在,那么将删除xs_kc表中所有不该学号相关的行,之后返回1。如果学号在xs中存在则直接返回零。

delimiter $$ create function delete_stu(xh char(6)) returns boolean begin declare stu char(6); select 姓名 into stu from xs where 学号=xh; if stu is null then delete from xs_kc where 学号=xh; return true; else return false; end if; end$$ delimiter ;

Page 15: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 15 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

1. 存储函数的调用 存储函数创建完后,就如同系统提供的内置函数(如VERSION()),

所以调用存储函数的方法也差不多,都是使用SELECT关键字。 语法格式:

SELECT 存储函数名 ([参数[,...]]) 例如,无参数调用存储函数。命令如下: select num_of_xs(); 执行结果如图所示。

例如,有参数调用存储函数。命令如下: select name_of_stu('081106'); 执行结果如图所示。

Page 16: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 16 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

【例6.18】创建一个存储函数,通过调用存储函数NAME_OF_STU获得学号的姓名,判断姓名是否是“王林”,是则返回王林的出生日期,丌是则返回“FALSE”。

delimiter $$ create function is_stu(xh char(6)) returns char(10) begin declare name char(8); select name_of_stu(xh) into name; if name= '王林' then return(select 出生日期 from xs where 学号=xh); else return 'false'; end if; end$$ delimiter ;

Page 17: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 17 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

接着调用存储函数is_stu查看结果:

select is_stu('081102');

执行结果如图所示。

select is_stu('081101');

执行结果如图所示。

Page 18: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 18 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

2. 删除存储函数

删除存储函数与删除存储过程的方法基本一样,都使用DROP

FUNCTION语句。

语法格式:

DROP FUNCTION [IF EXISTS] 存储过程名

例如,删除存储函数num_of_xs。 drop function if exists num_of_xs;

Page 19: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 19 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

3、使用ALTER FUNCTION语句可以修改存储函数的特征。

语法格式:

ALTER FUNCTION 存储过程名 [特征 ...] 注意:要修改存储函数的内容则要采用先删除后定义的方法。

Page 20: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 20 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

4、使用SHOW STATUS语句

Show status语句可以查看存储过程或存储函数所操作的数据库对

象,例如:存储过程或存储函数的名称、类型、定义、修改时间等信息

show [ procedure | function ] status [like‘pattern’]

说明:

like‘pattern’表示可以匹配存储过程或存储函数名称。

Page 21: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 21 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.2.2 存储函数的调用、删除和修改

5、使用show create 语句

Show create语句可以查看存储过程或存储函数的详细定义状态,

例如:存储过程或存储函数的字符集等信息。

show create [ procedure | function ] sp_name

说明:

sp_name表示存储过程或存储函数的名称。

Page 22: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 22 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

练习

1、创建一个存储函数count1_xs,用于统计xs表中男生的总人数;

2、创建一个存储函数stu_zhuanye,根据指定的学生学号,返回该学

生所在的专业名。

3、创建一个存储函数,通过调用存储函数stu_zhuanye获得学生的专

业名,然后返回该专业的总人数。

Page 23: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 23 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

练习

1、创建一个存储函数count1_xs,用于统计xs表中男生的总人数;

delimiter $$ create function count1_xs() returns integer begin return (select count(*) from xs where 性别=1); end$$ delimiter ; select count1_xs(); select count(*) from xs where 性别=1;

Page 24: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 24 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

练习

2、创建一个存储函数stu_zhuanye,根据指定的学生学号,返回该学生所在的专业名。

delimiter $$ create function stu_zhuanye( xh char(6)) returns char(10) begin return (select 专业名 from xs where 学号=xh); end$$ delimiter ; select stu_zhuanye(‘081101’); select 专业名 from xs where 学号=‘081101’;

Page 25: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 25 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

练习

3、创建一个存储函数,通过调用存储函数stu_zhuanye获得学生的专业名,然后返回该专业的总人数。

delimiter $$ create function count_zhuanye( xh char(6)) returns integer begin declare zhuanye char(10); select stu_zhuanye(xh) into zhuanye; return (select count(*) from xs where 专业=zhuanye); end$$ delimiter ; select count_zhuanye(‘081101’);

Page 26: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 26 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

1、存储函数不能拥有输出参数,由于存储函数本身就是输出参数;而存储过程可

以拥有输出参数;

2、存储函数只能返回单个值,而存储过程可以通过out参数返回多个值;

3、可以直接对存储函数进行调用,而不需要使用call语句;而对存储过程的调用

,需要使用call语句;

4、存储函数中必须包含一条return语句,而这条特殊的sql语句不允许包含在存储

过程中。

5、存储函数可以嵌套在sql语句中使用,比如可以在select语句中作为查询语句的

一个部分调用,但是存储过程一般是作为一个独立的部分来执行。

思考??

MySQL存储过程和存储函数有什么区别?

Page 27: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 27 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器 触发器是一种维护数据的完整性或者执行其它特殊任务的存储过程。

当有操作影响到触发器保护的数据时,触发器自动执行。 1. 创建触发器CREATE TRIGGER 语法格式:

CREATE TRIGGER 触发器名 触发时刻 触发事件 ON 表名 FOR EACH ROW 触发器动作

说明: - 触发时刻:有两个选项BEFORE和AFTER,以表示触发器是在激活它

的语句之前或之后触发。

- 触发事件:指明了激活触发程序的语句的类型,可以是insert、

delete或者update。

Page 28: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 28 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

-表名:表示在该表上发生触发事件才会激活触发器。同一个表不能

拥有两个具有相同触发时刻和事件的触发器。

例如,对于某一表,不能有两个BEFORE UPDATE触发器,但可以有1个BEFORE

UPDATE触发器和1个BEFORE INSERT触发器,或1个BEFORE UPDATE触发器和1个AFTER

UPDATE触发器。

-FOR EACH ROW:对于受触发事件影响的每一行,都要激活触发

器的动作。

例如,使用一条语句向一个表中添加多个行,触发器会对每一行执行相应触发

器动作。

-触发器动作:包含触发器激活时将要执行的语句。如果要执行多个

语句,可使用BEGIN ... END复合语句结构。

Page 29: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 29 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

【例6.19】创建一个表table1,其中只有一列a。在表上创建一个触发

器,每次插入操作时,将用户变量str的值设为“trigger is working”。

create table table1(a integer); create trigger table1_insert after insert on table1 for each row set @str= ' trigger is working ';

insert into table1 values(10);

select @str;

执行结果如图所示。

Page 30: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 30 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

(1)触发器中关联表中的列

在MySQL触发器中的SQL语句可以关联表中的任意列。但不能直接使用

列的名称去标志,那会使系统混淆,因为激活触发器的语句可能已经修改、

删除或添加了新的列名,而列的旧名同时存在。

因此必须用‚NEW.列名‛引用新行的一列,用‚OLD.列名‛引用更新

或删除它之前的已有行的一列。

注意:

- 对于INSERT触发事件,只有NEW是合法的;

- 对于DELETE触发事件,只有OLD才合法;

- 而UPDATE触发事件可以与NEW或OLD同时使用。

Page 31: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 31 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

【例6.20】创建一个触发器,当删除表xs中某个学生的信息时,同时将xs_kc表中不该学生有关的数据全部删除。

delimiter $$ create trigger xs_delete after delete on xs for each row begin delete from xs_kc where 学号=old.学号; end$$ delimiter ; delete from xs where 学号='081101'; select * from xs_kc;

Page 32: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 32 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

【例6.21】创建一个触发器,当修改xs_kc表中数据时,如果修改后的成绩小于60分,则触发器将该成绩对应的课程学分修改为0,否则将学分改成对应课程的学分。

delimiter $$ create trigger xs_kc_update before update on xs_kc for each row begin declare xf int(1); select 学分 into xf from kc where 课程号=new.课程号; if new.成绩<60 then set new.学分=0; else set new.学分=xf; end if; end$$ delimiter ;

Page 33: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 33 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

【例6.22】创建触发器,实现当向xs_kc表插入一行数据时,根据成绩对xs表的总学分进行修改。如果成绩>=60,总学分加上该课程的学分,否则总学分丌变。

delimiter $$ create trigger xs_kc_zxf after insert on xs_kc for each row begin declare xf int(1); select 学分 into xf from kc where 课程号=new.课程号; if new.成绩>=60 then update xs set 总学分=总学分+xf where 学号=new.学号; end if; end$$ delimiter;

Page 34: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 34 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

(2)触发器中调用存储过程

在触发器中还可以调用存储过程。

【例6.23】假设xscj数据库中有一个不xs表结构完全一样的表

student,创建一个触发器,在xs表中添加数据的时候,调用存储过程,

将student表中的数据不xs表同步。

定义存储过程:

delimiter $$ create procedure changes() begin replace into student select * from xs; end$$ delimiter;

Page 35: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 35 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

接着创建触发器: create trigger student_change after insert on xs for each row call changes(); 验证: insert into xs values('091102', '王大庆', '计算机', 1, '1994-08-14', 48, null,null); select * from student; 执行结果为:

Page 36: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 36 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.3 触发器

2. 触发器删除

和其他数据库对象一样,使用DROP语句即可将触发器从数据库中删除。

语法格式:

DROP TRIGGER [schema_name.]trigger_name

说明:

- trigger_name指要删除的触发器名称。

- schema_name为所在数据库的名称,如果在当前数据库,可以省略。

例如,删除触发器xs_delete。 drop trigger xs_delete;

Page 37: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 37 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4 事件

触发器是在某些事情发生的时候启动,而事件是在满足相应时刻的时

候启动,都是数据库的过程式数据库对象。创建事件可以使用CREATE

EVENT语句。

语法格式:

CREATE EVENT 事件名

ON SCHEDULE schedule

[ON COMPLETION [NOT] PRESERVE]

[ENABLE | DISABLE | DISABLE ON SLAVE]

[COMMENT 'comment']

DO sql语句;

Page 38: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 38 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.1 创建事件

(1)schedule格式:

AT 时间点 [+ INTERVAL 时间间隔]

| EVERY 时间间隔

[ STARTS 时间点[+ INTERVAL时间间隔]]

[ ENDS 时间点[+ INTERVAL时间间隔]]

说明:

- schedule:时间调度,表示事件何时发生或者每隔多久发生一次。 - AT子句:表示在某个时刻事件发生。在指定时间点,后面可以加上一个时间间

隔,由一个数值和单位构成,count是间隔时间的数值。 - EVERY子句:表示在指定时间区间内每隔多长时间事件发生一次。 - STARTS子句指定开始时间。 - ENDS子句指定结束时间。

Page 39: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 39 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.1 创建事件

(2)interval 格式

count { YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |

WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |

DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND }

Page 40: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 40 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.1 创建事件

(3)sql语句:

包含事件启动时执行的代码。如果包含多条语句,可以使用

BEGIN…END复合结构。

(4)事件的属性:

对于每一个事件都可以定义几个属性。

- ON COMPLETION [NOT] PRESERVE:NOT表示事件最后一次调用后将自动删除该事件

(默认),否则最后一次调用后将保留该事件。

- ENABLE | DISABLE | DISABLE ON SLAVE:

- ENABLE表示该事件是活动的,活动意味着调度器检查事件动作是否必须调用。

- DISABLE表示该事件是关闭的,关闭意味着事件的声明存储到目录中,但是调度

器不会检查它是否应该调用。

- DISABLE ON SLAVE表示事件在从机中是关闭的。如果不指定任何选项,在一个

事件创建之后,它立即变为活动的。

Page 41: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 41 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.1 创建事件

一个打开的事件可以执行一次或多次,一个事件的执行称作调用事件。每次调用一个事件,MySQL都处理事件动作。

MySQL事件调度器负责调用事件。这个模块是MySQL数据库服务器的一部分。它不断地监视一个事件是否需要调用。

要创建事件,必须打开调度器。可以使用系统变量EVENT_SCHEDULER来打开事件调度器,TRUE为打开,FALSE为关闭:

SET GLOBAL EVENT_SCHEDULER = TRUE;

【例6.24】创建一个立即启动的事件。

create event direct on schedule at now() do insert into xs values('091103', '张建', '软件工程', 1,

'1994-06-05', 50,null,null);

Page 42: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 42 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.1 创建事件

【例6.25】创建一个30秒后启动的事件。 create event thrityseconds on schedule at now()+interval 30 second do insert into xs values('091104', '陈建', '软件工程', 1,

'1994-08-16', 50,null,null);

Page 43: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 43 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.1 创建事件

【例6.26】创建一个事件,它每个月启动一次,开始于下一个月并且在2014年的12月31日结束。

delimiter $$ create event startmonth on schedule every 1 month starts curdate()+interval 1 month ends '2014-12-31' do begin if year(curdate())<2014 then insert into xs values('091105', '王建', '软件工程', 1, '1994-03-

16',48,null,null); end if; end$$ delimiter ;

Page 44: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 44 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.2 修改和删除事件

1. 修改事件 事件在创建后可以通过ALTER EVENT语句来修改其定义和相关属性。ALTER

EVENT语句与CREATE EVENT语句格式相仿,用户可以使用一条ALTER EVENT语句让

一个事件关闭或再次让它活动。当然,如果一个事件最后一次调用后已经不存在

了,就无法修改了。

语法格式: ALTER EVENT event_name [ON SCHEDULE schedule] [ON COMPLETION [NOT] PRESERVE] [RENAME TO new_event_name] [ENABLE | DISABLE | DISABLE ON SLAVE] [COMMENT 'comment'] [DO sql_statement] 说明:用户还可以使用一条RENAME TO子句修改事件的名称。

Page 45: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 45 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.2 修改和删除事件

【例6.27】将事件startmonth的名字改成firstmonth。 alter event startmonth rename to firstmonth;

Page 46: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 46 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

6.4.2 修改和删除事件

2. 删除事件

删除事件,语法格式:

DROP EVENT [IF EXISTS][database name.] event name

例如,删除名为direct的事件。

drop event direct;

Page 47: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 47 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

案例 create table test1(a1 int); create table test2(a2 int); create table test3(a3 int not null auto_increment primary key); create table test4 (a4 int not null auto_increment primary key,b4 int default 0); delimiter $$ create trigger testref before insert on test1 for each row begin insert into test2 set a2=new.a1; Delete from test3 where a3=new.a1; Update test4 set b4=b4+1 where a4=new.a1; end$$ delimiter ; Insert into test3(a3) values (null), (null), (null), (null), (null),(null),

(null), (null), (null), (null); Insert into test4(a4) values (0), (0), (0), (0), (0), (0), (0), (0), (0), (0); Insert into test1 values (1),(3),(1),(7),(1),(8),(4),(4);

Page 48: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 48 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

案例

执行下列查询语句后,每个表的结果?

Select * from test1;

Select * from test2;

Select * from test3;

Select * from test4;

Page 49: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 49 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

案例 create table test1(a1 int); create table test2(a2 int); create table test3(a3 int not null auto_increment primary key); create table test4 (a4 int not null auto_increment primary key,b4 int default 0); delimiter $$ create trigger testref before insert on test1 for each row begin insert into test2 set a2=new.a1; Delete from test3 where a3=new.a1; Update test4 set b4=b4+1 where a4=new.a1; end$$ delimiter ; Insert into test3(a3) values (null), (null), (null), (null), (null),(null),

(null), (null), (null), (null); Insert into test4(a4) values (0), (0), (0), (0), (0), (0), (0), (0), (0), (0); Insert into test1 values (1),(3),(1),(7),(1),(8),(4),(4);

Page 50: MySQL数据库应用fileapi.it.hactcm.edu.cn › MySQL › file › 2020 › 5 › 22 › ...2020/05/22  · 《MySQL数据库应用》 第 4 页 6.1.3游标及其应用 一条select……into语句返回的是带有值的一行,这样可以

第 50 页 《MySQL数据库应用》 http://mysql.xg.hactcm.edu.cn/

案例

Select * from test1;

Select * from test2;

Select * from test3;

Select * from test4;