MySQL——存储过程和函数

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: MySQL——存储过程和函数

前言


存储过程和函数是在数据库中定义的一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句。存储过程和函数可以避免开发人员重复编写相同的SQL语句。而且,存储过程和函数是在MySQL服务器中存储和执行的,可以减少客户器端和服务端的数据传输。


c7f7b046af3a46a8a925ef1d667a6930.jpg

 通过本次的学习,将了解存储过程的定义、作用,还可以了解创建、使用、查看、修改及删除存储过程及函数的方法。


一、创建存储过程


创建存储过程和函数是指将经常使用的一组SQL语句组合在一起,并将这些SQL语句当作一个整体存储在MySQL服务器中。存储程序可以分为存储过程和函数。在MySQL中创建存储过程使用的语句CREATE PROCEDURE。其语法形式如下:


       CREATE PROCEDURE procedure_name([proc_param[,…]])  


                routine_body  


       在上述语句中,参数procedure_name表示所要创建的存储过程名字,参数proc_param表示存储过程的参数,参数routine_body表示存储过程的SQL语句代码,可以用BEGIN…END来标志SQL语句的开始和结束。


       提示: 在具体创建存储过程时,存储过程名不能与已经存在的存储过程名重名,实战中推荐存储过程名命名为procedure_xxx或者proc_xxx。


       proc_param中每个参数的语法形式如下:


                   [IN|OUT|INOUT] param_name type


       在上述语句中,每个参数由三部分组成,分别为输入/输出类型、参数名和参数类型。其中,输入/输出类型有三种类型,分别为IN(表示输入类型)、OUT(表示输出类型)、INOUT(表示输入/输出类型)。param_name表示参数名;type表示参数类型,可以是MySQL软件所支持的任意一个数据类型。


【示例11-1】

mysql>  use school;   #选择数据库school                                            


mysql> DELIMITER $$                                                                                


mysql> create PROCEDURE  proc_delete_student (IN sid int )                                  


       BEGIN


        declare cid  int ;   #定义变量cid                          


  Select class_id into cid from student where id = sid; #通过查询语句设置变量                                                                      


        delete from grade where id = sid;  #删除成绩表中的记录


        delete from student where id = sid;   #删除学生表中的记录                                                    


        update class set count=count-1 where id = cid; #更新班级表中的记录  


       END;                                                                      


       $$                                                                          


        DELIMITER ;                                                                


mysql>  call proc_delete_student(2);    #调用存储过程        


二、存储过程中使用变量


在存储过程和函数中,可以定义和使用变量。用户可以使用关键字DECLARE来定义变量,然后为变量赋值。这些变量的作用范围是在BEGIN…END程序段中。

       1.定义变量


在MySQL中,可以使用DECLARE关键字来定义变量。定义变量的基本语法如下:


                   DECLARE var_name[,…] type [DEFAULT value]  


               其中,关键字DECLARE是用来声明变量的;参数var_name是变量的名称,可以同时定义多个变量;参数type用来指定变量的类型;DEFAULT value子句将变量默认值设置为value,没有使用DEFAULT子句时,默认值为NULL。


               定义变量cid,数据类型为INT型,默认值为10,代码如下:


                 DECLARE cid INT DEFAULT 10;    


2.为变量赋值


在MySQL中可以使用关键字SET来为变量赋值,SET语句的基本语法如下:


                   SET var_name=expr[,var_name=expr]…


               其中,关键字SET用来为变量赋值;参数var_name是变量的名称;参数expr是赋值表达式。一个SET语句可以同时为多个变量赋值,各个变量的赋值语句之间用逗号隔开。


               例如,将变量tmp_id赋值为88,代码如下:


               SET tmp_id = 88;


               在MySQL中,还可以使用SELECT…INTO语句为变量赋值。其基本语法如下:


                    SELECT col_name[,…] INTO var_name[,…]    


                    FROM table_name WHERE condition        


           其中,参数col_name表示查询的字段名称;参数var_name是变量的名称;参数table_name指表的名称;参数condition指查询条件。


       【示例11-2】从表employee中查询id为3的记录,将该记录的id值赋给变量tmp_id,代码如下:


           SELECT id INTO tmp_id


               FROM grade WEHRE id=sid;        


mysql>  use school;   #选择数据库school                                            


mysql>  drop  PROCEDURE if exists query_student_class_info;                                                                            


mysql> DELIMITER $$                                                                              


mysql> create procedure  query_student_class_info (IN sid int, OUT cname varchar(128), OUT ccount  int)                                  


       BEGIN  


           declare tmp_name varchar(128);


           declare tmp_count int;


           declare tmp_cid  int;


           select class_id into tmp_cid from student where id = sid;        


           select name, count into tmp_name, tmp_count from class where id = tmp_cid;


           set cname = tmp_name, ccount = tmp_count;


        END;  


        $$                                                                          


        DELIMITER ;                                                                


mysql>  call query_student_class_info(4, @name, @count);    #调用存储过程


mysql>  select @name, @count;                  

三、光标的使用


查询语句可能查询出多条记录,在存储过程和函数中使用光标来逐条读取查询结果集中的记录。有些书上将光标称为游标。光标的使用包括声明光标、打开光标、使用光标和关闭光标。光标必须声明在处理程序之前,并且声明在变量和条件之后。


1.打开光标

       在MySQL中,可以使用DECLARE关键字来声明光标,其基本语法如下:


                   DECLARE cursor_name CURSOR        


                   FOR select_statement;                


       其中,参数cursor_name表示光标的名称;参数select_statement表示SELECT语句的内容。


       【示例11-2】下面声明一个名为cur_student的光标,代码如下:


mysql>use school;#选择数据库                                                                                                                      


mysql> DELIMITER $$                                                                                


mysql> create procedure  query_student (IN sid int, OUT cname varchar(128), OUT class_id  int )                                    


       BEGIN                                                


           DECLARE cur_student CURSOR                    


               FOR SELECT name, class_id FROM  student;  


        END;                                                


        $$                                                                          


        DELIMITER ;                  



   在上面的示例中,光标的名称为cur_student;SELECT语句部分是从表student中查询出字段name和class_id的值。

2.打开光标


在MySQL中,使用关键字OPEN来打开光标,其基本语法如下:


           OPEN cursor_name;


       其中,参数cursor_name表示光标的名称。


       下面代码打开一个名为cur_student的光标,代码如下:


           OPEN cur_student;


3.使用光标


  FETCH cursor_name


             INTO var_name[,var_name…];


       其中,参数cursor_name表示光标的名称;参数var_name表示将光标中的SELECT语句查询出来的信息存入该参数中。var_name必须在声明光标之前就定义好。


use school;   #选择数据库school


DELIMITER $$


create procedure query_student (IN sid int, OUT cname varchar(128), OUT cid int)                                                                                  


BEGIN


       declare tmp_name varchar(128);


       declare tmp_cid int;


       declare done int default 0;


       declare cur_student CURSOR FOR SELECT name,class_Id from student where id=sid;


       declare continue handler for not found set done = 1; #将结束标志绑定到游标上


       open  cur_student;


        select done;


       fetch cur_student into tmp_name, tmp_cid;


       select done;


        select tmp_name, tmp_cid;


        close cur_student;


         set cname = tmp_name, cid = tmp_cid;


       END;


       $$


       DELIMITER ;



4.关闭光标


 在MySQL中,使用关键字CLOSE来关闭光标,其基本语法如下:


           CLOSE cursor_name;


       其中,参数cursor_name表示光标的名称。


       例如: 关闭一个名为cur_student的光标,代码如下:


           CLOSE cur_student;


       在上面的示例中,关闭了这个名称为cur_student的光标。关闭了之后就不能使用FETCH来使用光标了。提示


       如果存储过程或函数中执行了SELECT语句,并且SELECT语句会查询出多条记录,这种情况最好使用光标来逐条读取记录,光标必须在处理程序之前且在变量和条件之后声明,而且光标使用完毕后一定要关闭。


四、流程控制的作用

1.IF语句


 IF语句用来进行条件判断。根据条件执行不同的语句。其语法的基本形式如下:


IF search_condition THEN statement_list      


[ELSEIF search_condition THEN statement_list] ...


[ELSE statement_list]                          


END  IF                                      


       参数search_condition表示条件判断语句;参数statement_list表示不同条件的执行语句。


---【示例11-4】下面是一个IF语句的示例,代码如下:


IF age>20 THEN SET @count1=@count1+1;  


   ELSEIF age=20 THEN @count2=@count2+1;


   ELSE @count3=@count3+1;              


 END IF;                                      


       该示例根据age与20的大小关系来执行不同的SET语句。如果age值大于20,将count1的值加1;如果age值等于20,就将count2的值加1;其他情况将count3的值加1。IF语句都需要使用END IF来结束。


#课堂范例


mysql>  use school;   #选择数据库school                                                                                                                        


mysql> DELIMITER $$                                                                              


mysql> create procedure proc_test_if (IN input int, OUT output int)


       begin


           if input>20 then set input=input+1;


           elseif input=20 then  set input=input+2;


           else  set input = input+3;


           end if;


           set output = input;


       end;


mysql>  $$                                                                                


mysql>  DELIMITER ;    

2.CASE语句



 CASE语句可实现比IF语句更复杂的条件判断,其语法的基本形式如下:


CASE case_value                                


WHEN when_value THEN statement_list          


[ WHEN when_value THEN statement_list ]        


[ELSE statement_list]                              


END CASE                                        


       其中,参数case_value表示条件判断的变量;参数when_value表示变量的取值;参数statement_list表示不同when_value值的执行语句。


---【示例11-5】下面是一个CASE语句的示例。代码如下:


CASE level                                  


     WHEN 20 THEN SET attack = attack + 5;


     WHEN 30 THEN SET attack = attack + 10;


     WHEN 40 THEN SET attack = attack + 15;


     ELSE SET attack = attack + 1;


END CASE          


       当级别level值为20时,attack值加5;当级别level值为30时,attack值加10;当级别level值为40时,attack值加15;否则,attack + 1。CASE语句使用END CASE结束。

3.LOOP语句


LOOP语句可以使某些特定的语句重复执行,实现一个简单的循环。LOOP语句本身没有停止循环,只有遇到LEAVE语句等才能停止循环。LOOP语句的语句形式如下:


  [begin_label:] LOOP            


  statement_list                


  END LOOP [end_label]        


       其中,参数begin_label和参数end_label分别表示循环开始和结束的标志,这两个标志必须相同,而且都可以省略;参数statement_list表示需要循坏执行的语句。


---【示例11-6】下面是一个LOOP语句的示例,代码如下:


add_num:LOOP                


    SET @count = @count + 1;


END LOOP add_num;          


       该示例循环执行count加1的操作。因为没有跳出循环的语句,这个循环成了一个死循环。LOOP循环都以END LOOP结束。


4.LEAVE语句


 LEAVE语句主要用于跳出循环控制,其语法形式如下:


LEAVE label                


       其中,参数label表示循环的标志。


---【示例11-7】下面是一个LEAVE语句的示例。代码如下:


add_num: LOOP            


SET @count=@count + 1;


Select @count;


IF @count = 100 THEN


   LEAVE add_num;    


END IF;


END LOOP add_num;        


       该示例循环执行count值加1的操作。当count的值等于100时,LEAVE语句跳出循环。


5.ITERATE语句


  ITERATE语句也是用来跳出循环的语句,但是ITERATE语句是跳出本次循环,然后直接进入下一次循环,ITERATE语句的语法形式如下:


 ITERATE label


       其中,参数label表示循环的标志。


---【示例11-8】下面是一个ITERATE语句的示例。代码如下:


add_num1:LOOP            


   Set @count = @count +1


   IF @count=100 THEN    


       LEAVE add_num1      


   ELSE IF MOD(@count, 3) = 0 then


       ITERATE add_num1;  


    Select * from student;  


END LOOP add_num1;      


       该示例循环执行count加1的操作,count的值为100时结束循环。如果count的值能够整除3,就跳出本次循环,不再执行下面的SELECT语句。


       注意: LEAVE语句和ITERATE语句都用来跳出循环语句,但是两者的功能是不一样的。LEAVE语句是跳出整个循环,然后执行循环后面的程序,和C++ break 相似。ITERATE语句是跳出本次循环,然后进入下一次循环,和C++ continue 相似。使用这两个语句时一定要区分清楚。


6.REPEAT语句


 REPEAT语句是有条件控制的循环语句。当满足特定条件时,就会跳出循环语句。REPEAT语句的基本语法形式如下:


[begin_label:] REPEAT      


       statement_list;      


    UNTIL search_condition


END REPEAT [end_label]    


       其中,参数statement_list表示循环的执行语句;参数search_condition表示结束循环的条件,满足该条件时循环结束。


---【示例11-9】下面是一个REPEAT语句的示例。代码如下:


REPEAT                      


    SET @count=@count+1;  


    UNTIL @count=100      


END REPEAT;                  


       该示例循环执行count加1的操作,count值为100时结束循环。REPEAT循环都用END REPEAT结束。

7.WHILE语句

 WHILE语句也是有条件控制的循环语句,但WHILE语句和REPEAT语句是不一样的。WHILE语句是当满足条件时执行循环内的语句。WHILE语句的基本语法形式如下:


[begin_label:] WHILE search_condition DO  


       Statement_list                    


END WHILE [end_label]                    


       其中,参数statement_condition表示循环执行的条件,满足该条件时循环执行;参数statement_list表示循环的执行语句。


---【示例11-10】下面是一个WHILE语句的示例。代码如下:


WHILE @count<100 DO      


   SET @count = @count + 1;


END WHILE;                  

五、流程控制综合运用


mysql>  use school;   #选择数据库school


mysql> DELIMITER $$                                                                              


mysql> create procedure query_all_students (IN sid int, OUT cname varchar(128), OUT cid int)


BEGIN


       declare tmp_name varchar(128);    #必须定义在声明光标之前


       declare tmp_cid  int;


        declare  done int default 0;


       declare cur_student CURSOR FOR SELECT name, class_id FROM  student ;


       declare continue handler for not found set done = 1; #将结束标志绑定到游标上


       open  cur_student;


       read_loop:LOOP      #循环读取


       fetch cur_student into tmp_name, tmp_cid;


               IF done=1 then


                       Leave read_loop;


               END IF;


               select tmp_name, tmp_cid;  


       END LOOP read_loop;


       close cur_student;


       set cname = tmp_name, cid = tmp_cid;


END;


mysql>  $$


mysql>  DELIMITER ;  

【示例11-12】在学生表中插入一条记录,并返回记录的自增长id

mysql>  use school;   #选择数据库school


mysql> DELIMITER $$  


mysql> create procedure fetch_insert_student_id (IN p_name varchar(128), in p_class_id int, IN p_sex char(1), OUT rid int)


               BEGIN


                       Insert into student (name, class_id, sex) values(p_name, p_class_id, p_sex);


                       select last_insert_id() as rid;


               END;


mysql>  $$


mysql>  DELIMITER ;  


六、查看存储过程

存储过程创建以后,用户可以通过SHOW STATUS语句来查看存储过程的状态,也可以通过SHOW CREATE语句来查看存储过程的定义。用户也可以通过查询information_schema数据库下的Routines表来查看存储过程的信息。本节将详细讲解查看存储过程的状态与定义的方法。


1.SHOW STATUS语句查看存储过程

在MySQL中,可以通过SHOW STATUS语句。其基本语法形式如下:


    SHOW PROCEDURE STATUS  [ like ‘pattern’ ] ;


       其中,参数PROCEDURE表示查询存储过程;参数LIKE 'pattern'用来匹配存储过程的名称。


图11-13的执行结果显示了存储过程的创建时间、修改时间和字符集等信息。


389d7f826c61446e8e7d7e32e90f62ce.png

2.使用SHOW CREATE语句查看存储过程的定义


       在MySQL中,可以通过SHOW CREATE语句查看存储过程的状态,语法形式如下:


   SHOW CREATE PROCEDURE proc_name    


       其中,参数PROCEDURE表示查询存储过程;参数proc_name表示存储过程的名称。


---【示例11-14】查询名为proc_delete_student的存储过程的状态,代码如下,执行结果如下图所示。


   SHOW CREATE PROCEDURE proc_delete_student \G


59f0bd9946724369956f10bd59516028.png

3.从information_schema.Routine表中查看存储过程的信息


       存储过程和函数的信息存储在information_schema数据库下的Routines表中。可以通过查询该表的记录来查询存储过程和函数的信息。其基本语法形式如下:


       SELECT * FROM information_schema.Routines


        Where ROUTINE_NAME = ‘proc_name’;


       其中,字段ROUTINE_NAME是Routines 存储存储过程和函数的列名称;参数proc_name表示存储过程或函数的名称。


---【示例11-15】下面从Routines表中查询名为proc_delete_student的存储过程信息,具体SQL代码如下,执行结果如下图所示。


select routine_definition from information_schema.Routines where         routine_name='proc_delete_student';


36ad729b874f4ce889b51b52e002e9b7.png

七、存储过程的删除


 在MySQL中删除存储过程通过SQL语句DROP完成:


   DROP PROCEDURE proc_name;            


       在上述语句中,关键字DROP PROCEDURE用来表示实现删除存储过程,参数proc_name表示所要删除的存储过程名称。


---【示例11-16】执行SQL语句DROP PROCEDURE,删除存储过程对象proc_delete_student,具体步骤如下:


   DROP PROCEDURE proc_delete_student;

总结

               以上就是我的学习总结。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
JSON 关系型数据库 MySQL
Mysql(5)—函数
MySQL提供了许多内置的函数以帮助用户进行数据操作和分析。这些函数可以分为几类,包括聚合函数、字符串函数、数值函数、日期和时间函数、控制流函数等。
70 1
Mysql(5)—函数
|
13天前
|
关系型数据库 MySQL Serverless
MySQL函数
最常用的MySQL函数,包括聚合函数,字符串函数,日期时间函数,控制流函数等
|
16天前
|
存储 SQL NoSQL
|
16天前
|
SQL NoSQL 关系型数据库
|
1月前
|
存储 SQL 关系型数据库
MySQL 存储函数及调用
MySQL 存储函数及调用
54 3
|
1月前
|
存储 关系型数据库 MySQL
MySQL 存储过程返回更新前记录
MySQL 存储过程返回更新前记录
48 3
|
1月前
|
存储 SQL 关系型数据库
MySQL 存储过程错误信息不打印在控制台
MySQL 存储过程错误信息不打印在控制台
57 1
|
27天前
|
关系型数据库 MySQL 数据库
mysql中tonumber函数使用要注意什么
在处理这类转换操作时,考虑周全,利用提供的高性能云服务器资源,可以进一步提升数据库处理效率,确保数据操作的稳定性和安全性,尤其是在处理大量数据转换和运算密集型应用时。
84 0
|
1月前
|
关系型数据库 MySQL 数据处理
企业级应用 mysql 日期函数变量,干货已整理
本文详细介绍了如何在MySQL8.0中使用DATE_FORMAT函数进行日期格式的转换,包括当日、昨日及不同时间段的数据获取,并提供了实际的ETL应用场景和注意事项,有助于提升数据处理的灵活性和一致性。
40 0
|
1月前
|
存储 SQL 关系型数据库
MySql数据库---存储过程
MySql数据库---存储过程
33 5