什么?还不了解MySQLl存储过程与触发器的建立使用?

或许你曾经去面试的时候被问到过关于mysql数据库的存储过程和触发器的问题,若是你还不懂能够看下这篇关于存储过程和触发器的文章,但愿能帮助到有须要的朋友。javascript

Mysql存储过程与触发器java

本篇文章主要是简单解释mysql中存储过程的建立、调用以及介绍触发器和如何建立触发器。那么关于存储过程和触发器那些官方理论的介绍我就不在这里啰嗦了。mysql

1数据表的准备面试

下面全部例子中用到的表的建立脚本。tb_user是下面例子中的用户表,tb_blog是博客表,tb_user_log是用户信息更新日记表。sql

 
  1. use db_mybatis; 
  2.  
  3. create table tb_user( 
  4.     id int(11) unsigned not null auto_increment, 
  5.     uname varchar(50) not null, 
  6.     pwd varchar(50) not null, 
  7.     primary key (id) 
  8. )engine=InnoDB default charset=utf8; 
  9.  
  10.  
  11. create table tb_blog( 
  12.     id int(11) unsigned not null auto_increment, 
  13.     title varchar(50) not null, 
  14.     details varchar(50) not null, 
  15.     create_date datetime not null, 
  16.     update_date datetime not null, 
  17.     primary key (id) 
  18. )engine=InnoDB default charset=utf8; 
  19.  
  20. create table tb_user_log( 
  21.     id int(11) unsigned not null auto_increment, 
  22.     create_date datetime not null, 
  23.     details varchar(255) not null, 
  24.     primary key (id) 
  25. )engine=InnoDB default charset=utf8; 

2“delimiter //”的解释数据库

mysql默认以';'做为语句结束符。咱们都知道,在mysql命令行模式下,当输入一条语句时,若是不加‘;’回车是不会执行输入的sql语句的。如:mybatis

 
  1. mysql> select * from tb_blog  
  2.     ->  
  3.     ->  
  4.     ->  
  5.     ->  
  6.     -> ; 
  7. +----+--------+--------------+---------------------+---------------------+ 
  8. | id | title  | details      | create_date         | update_date         | 
  9. +----+--------+--------------+---------------------+---------------------+ 
  10. |  2 | dsssss | 这是内容     | 2018-08-13 02:42:44 | 2018-08-15 16:39:16 | 
  11. |  3 | new1   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  12. |  4 | new2   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  13. |  5 | new3   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  14. |  6 | new4   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  15. +----+--------+--------------+---------------------+---------------------+ 
  16. 5 rows in set (0.01 sec) 

而delimiter的做用就是修改语句结束符,如delimiter &就是将sql语句的结束为定义为'&'符号,当遇到'&'符号时,mysql判断为语句输入完成就会执行,看下面例子:函数

 
  1. mysql> delimiter & 
  2. mysql> select * from tb_blog 
  3.     ->  
  4.     -> & 
  5. +----+--------+--------------+---------------------+---------------------+ 
  6. | id | title  | details      | create_date         | update_date         | 
  7. +----+--------+--------------+---------------------+---------------------+ 
  8. |  2 | dsssss | 这是内容     | 2018-08-13 02:42:44 | 2018-08-15 16:42:54 | 
  9. |  3 | new1   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  10. |  4 | new2   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  11. |  5 | new3   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  12. |  6 | new4   | 这是内容     | 2018-08-13 02:42:44 | 2018-08-13 22:04:21 | 
  13. +----+--------+--------------+---------------------+---------------------+ 
  14. 5 rows in set (0.00 sec) 

因此,delimiter //的做用是将'//'做为语句的结束符,'//'能够是其余的字符,好比上面例子中使用'&';命令行

那么为何编写存储过程和触发器咱们须要将默认的';'修改成'//'做为sql语句结束符呢?由于咱们要在存储过程或触发器中执行sql语句,因此会用到';',若是不改其它符号而使用';'做为语句结束符的话,mysql遇到';'就看成一条语句完成了,而存储过程或触发器的sql语句都没写彻底呢,这样只会ERROR。blog

注意,在使用delimiter //将sql语句结束符改成'//'用完后(如完成建立存储过程)记得要使用delimiter ;将sql语句结束符改回为默认。

3存储过程

先来看两个简单的存储过程实例,对存储过程的建立和调用有一个模糊的印象。

 
  1. #实例一:建立查询全部博客的存储过程 
  2. drop procedure if exists select_procedure 
  3. delimiter // 
  4. create procedure select_procedure() 
  5.     begin 
  6.         select * from tb_blog; 
  7.     end // 
  8. delimiter ; 
  9. #调用 
  10. call select_procedure; 
  11.  
  12.  
  13. #实例二:更新博客修改时间的存储过程 
  14. drop procedure if exists update_blog_updatedate; 
  15. delimiter // 
  16. create procedure update_blog_updatedate(blogid int(11)) 
  17.     begin 
  18.         update tb_blog set update_date = sysdate() where id = blogid;#sysdate()获取当前日期+时间字符串(24小时格式) 
  19.     end // 
  20. delimiter ; 
  21. #调用 
  22. call update_blog_updatedate(2); 

好,下面我经过一个简单的存储过程实例来分析如何建立一个存储过程。先看例子:

 
  1. #建立更新博客标题的存储过程 
  2. drop procedure if exists update_blog;#若是存在该存储过程先删除 
  3. delimiter // 
  4. create procedure update_blog(blogid int(11)) 
  5.     begin 
  6.         start transaction;#开启事务 
  7.         update tb_blog set title='dsssss' where id=blogid;#要作的事情 
  8.         commit;#提交事务 
  9.     end // 
  10. delimiter ; 

上面实际建立存储过程的语句为

 
  1. create procedure update_blog(blogid int(11))#(参数1 参数类型(长度),参数2 参数类型(长度),...) 
  2.     begin 
  3.         start transaction;#开启事务 
  4.         update tb_blog set title='dsssss' where id=blogid;#要作的事情 
  5.         commit;#提交事务 
  6.     end // 

end后面的'//'是sql语句结束符,就是前面用delimiter //修改的sql语句结束符,因此从create到//就是一条完整的建立存储过程的sql语句。那么为何还要在前面加一条drop procedure if exists update_blog?其实你能够不加的,这条语句的做用只是当要建立的存储过程已经存在同名的存储过程时将已经存在的存储过程删除。

如今再来解析建立存储过程的这条语句,其中,update_blog时存储过程的名称,()内是调用该存储过程时要传递的参数,参数个数不限制,参数间用','分割,参数要声明类型,如blogid int(11),blogid就是参数名,int是类型,若是要指定长度则在类型后面加'(长度)'。

begin和end之间就是存储过程要作的事情。

使用call+存储过程名称来调用存储过程,若是存储过程定义了参数,那么须要在调用的时候传入参数,不然调用失败。

 
  1. call update_blog(2);#调用存储过程 

下面来看一个稍微成型点的存储过程。

 
  1. # 建立批量更新的存储过程 
  2. drop procedure if exists update_all_blog_date; 
  3. delimiter // 
  4. create procedure update_all_blog_date() 
  5.     begin 
  6.         declare id_index int(11) default 0;#定义变量id_index,类型为int,默认值为0 
  7.         declare blog_count int default 0; 
  8.         declare bid int; 
  9.         select count(*) into blog_count from tb_blog;#into blog_count 将查询结果赋值给blog_count变量 
  10.         if blog_count>0 then 
  11.             #start transaction; 
  12.             while id_index<=blog_count do 
  13.                 #update tb_blog set update_date = sysdate() where id in 
  14.                 #(select tb.id from (select id from tb_blog limit id_index,1) as tb); 
  15.                 #set id_index=id_index+1; 
  16.  
  17.                 select id into bid from tb_blog limit id_index,1; 
  18.                 update tb_blog set update_date = sysdate() where id = bid; 
  19.                 set id_index=id_index+1; 
  20.             end while; 
  21.             #commit; 
  22.         end if; 
  23.     end // 
  24. delimiter ; 
  25.  
  26. call update_all_blog_date; 

解析:

declare是定义变量的关键字,能够理解为javascript中的var关键字。定义变量必须是在存储过程的内部,即begin和end之间。变量的定义方式是declare关键字加变量名加变量类型,若是想指定默认值就在类型后面加上“default 默认值”。

select count(*) into blog_count from tb_blog语句是获取tb_blog表的总数赋值给blog_count,将查询结果赋值给某个变量使用into关键字。

set关键字是修改变量的值,将一个新的值写给set指定的变量。其它的就不作解释了,看不懂就须要学一下mysql的条件语句与循环语句了。

4Mysql中的触发器

触发器是什么?

触发器就是一个函数,当知足某种条件时才会触发其执行。

什么状况下使用触发器?

好比咱们要为用户所作的我的信息修改记录一条变动日记,那么是否是须要在修改完用户信息以后添加一条日记记录?若是不使用触发器咱们就须要执行两条sql语句,第一条是修改用户信息的sql语句,第二条是添加一个日记记录的sql语句。咱们在写业务逻辑代码的时候若是在多处地方可能对用户信息修改,在某处忘记了写日记记录也不奇怪。而若是使用触发器,当用户信息修改时触发触发器执行添加一条日记记录,这样也会比在业务代码中执行两条sql语句效率要高。

那么若是建立一个触发器呢?

 
  1. create trigger 触发器名称 after|before insert|delete|update on 表名 for each row 
  2. begin 
  3.     #触发器要作的事情 
  4. end 
  • 表名:将改触发器的触发条件挂载在哪张表上,也就是指定哪张表的操做知足条件时触发该触发器。
  • 触发器执行时机:after或者before,即以前仍是以后。
  • 触发的条件:insert|delete|update 便可选增删改时触发;好比alter insert,就是在添加完成以后触发,执行时机与触发条件可随意组合使用,即

before insert

before delete

before update

after insert

after delete

after update

  • for each row表示任何一条记录的操做知足触发条件都会触发触发器执行。

下面来看一个实例:在用户信息表tb_user中的记录被修改以后添加一条日记记录,记录修改时间和修改内容。

 
  1. drop trigger if exists on_user_info_chang_log; 
  2. delimiter // 
  3. create trigger on_user_info_chang_log after update on tb_user for each row 
  4. begin 
  5.     declare info varchar(255) charset utf8 default ''; 
  6.     set info = '修改以前的信息为:['; 
  7.     set info = concat(info,NEW.uname); 
  8.     set info = concat(info,','); 
  9.     set info = concat(info,New.pwd); 
  10.     set info = concat(info,'],修改以前的信息为:['); 
  11.     set info = concat(info,OLD.uname); 
  12.     set info = concat(info,','); 
  13.     set info = concat(info,OLD.pwd); 
  14.  
  15.     insert into tb_user_log (create_date,details) value(sysdate(),info); 
  16. end // 
  17. delimiter ; 

解析:

  • concat函数是字符串拼接函数
  • NEW是修改后的新的记录
  • OLD是修改前的旧的纪录
  • sysdate函数是获取当前系统日期时间字符串

下面咱们执行一条sql来触发该触发器

 
  1. update tb_user set uname='new_name' where id = 1; 

查看日记表中是否添加了一条记录。

相关文章
相关标签/搜索