简单的说,存储过程就是一条或者多条SQL语句的集合,可以理解为脚本,但是起作用不仅限于批处理,下面我们将重点学习如何使用创建存储函数和过程,变量的调用查看等,存储过程是MySQL的一个重点内容.
存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别是:CREATE PROCEDURE
和CREATE FUNCTION
.使用CALL语句
来调用存储过程,只能用输出变量返回值.函数可以从语句外调用(即通过引用函数名),也能返回标量值,存储过程也可以调用其他存储过程.
创建存储过程 创建存储过程,需要使用create procedure语句
,其基本语法格式如下:
create procedure proc_name ([proc_parameter]) [characteristics ...] routine_body
如上,create procedure
为用来创建存储函数的关键字,proc_name
为存储过程名称,proc_parameter
为指定存储过程的参数列表,列表的形式如下所示:
[ IN | OUT | INOUT ] param_name type
其中,IN
表示输入的参数,OUT
表示输出的参数,INOUT
表示即可以输入也可以输出,param_name
表示参数名称,type
表示参数的类型,该类型可以使MySQL数据库中任意的类型.
创建简单存储过程: 创建一个存储过程Proc()
,实现查询lyshark
数据表的所有字段.
MariaDB [lyshark]> delimiter / / MariaDB [lyshark]> create procedure Proc() - > BEGIN - > select * from lyshark; - > END / / Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> delimiter ; MariaDB [lyshark]> call Proc;
以上存储过程,只是执行了查询语句的操作,delimiter
语句的作用是方式结束符与冒号相冲突,当我们写完存储过程时,应该使用相同的闭合语句恢复.
创建带参存储过程: 创建一个存储过程,查询lyshark
表中记录,过程名称为CountProc
,并使用count(*)
计算后把结果放入参数param1
中,SQL语句如下:
MariaDB [lyshark]> delimiter / / MariaDB [lyshark]> create procedure CountProc(OUT param1 INT ) - > BEGIN - > select count (* ) into param1 from lyshark; - > END / / Query OK, 0 rows affected (0.01 sec) MariaDB [lyshark]> delimiter ;
当我们想要调用上面的存储过程是,需要指定一个变量名来接收返回结果,此处指定为temp
.
MariaDB [lyshark]> call CountProc(@temp ); Query OK, 1 row affected (0.00 sec) MariaDB [lyshark]> select @temp ; + | @temp | + | 17 | + 1 row in set (0.00 sec)
创建带参存储过程: 创建一个存储过程CountProc1
,然后调用这个过程,定义SQL语句如下:
MariaDB [lyshark]> delimiter / / MariaDB [lyshark]> create procedure CountProc1(IN id int ,OUT temp INT ) - > BEGIN - > select count (* ) into temp from lyshark where Gid= id; - > END / / Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> delimiter ;
接着我们调用CountProc1
这个存储过程,并给它传递相应的参数.
MariaDB [lyshark]> select count (* ) from lyshark where Gid= 101 ; + | count (* ) | + | 3 | + 1 row in set (0.00 sec)MariaDB [lyshark]> call CountProc1(101 ,@num ); Query OK, 1 row affected (0.00 sec) MariaDB [lyshark]> select @num ; + | @num | + | 3 | + 1 row in set (0.00 sec)
创建存储函数 存储函数的使用方法与MySQL内部函数的使用方法是一样的,在MySQL中,用户自己定义的存储函数与MySQL内部函数是一个性质的.区别在于,存储函数是用户自己定义的,而内部函数则是开发者编写的.
创建存储函数: 创建储存函数CountProc2
,然后调用这个函数,SQL语句如下:
MariaDB [lyshark]> delimiter / / MariaDB [lyshark]> create function CountProc2(myid INT ) - > returns int - > BEGIN - > return (select count (* ) from lyshark where Gid= myid); - > END / / Query OK, 0 rows affected (0.02 sec) MariaDB [lyshark]> delimiter ;
接着我们来调用这个存储函数,SQL语句如下:
MariaDB [lyshark]> select CountProc2(101 ); + | CountProc2(101 ) | + | 3 | + 1 row in set (0.00 sec)
以上可以看出,返回结果,虽然存储函数和存储过程的定义稍有不同,但是可以实现相同功能.
创建存储函数: 创建名称为NameZip
,该函数返回select
语句查询结果,数值类型为字符串,SQL语句如下:
MariaDB [lyshark]> delimiter / / MariaDB [lyshark]> create function NameZip() - > returns char (50 ) - > return (select s_name from suppliers where s_call= '4521' ); - > / / Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> delimiter ;
调用一下看看效果,SQL语句如下.
MariaDB [lyshark]> select s_name from suppliers where s_call = '4521' ; + | s_name | + | FastFruit. | + 1 row in set (0.00 sec)MariaDB [lyshark]> select NameZip(); + | NameZip() | + | FastFruit. | + 1 row in set (0.00 sec)
如果在存储函数中的RETURN语句返回一个类型不同于函数的型的值,返回值将被强制为恰当的类型.
提示:指定参数为IN,OUT或者INOUT只对PROCEDURE是合法的.FUNCTION中总是默认为IN参数.RETURNS子句只能对FUNCTION做指定,对函数而言这是强制的.它用来指定函数的返回类型,而且函数体必须包含一个RETURN value语句.
声明使用变量 变量可以在子程序中声明并使用,这些变量的作用范围实在BEGIN...END
程序中,本小姐将介绍定义和赋值一个变量,定义变量的语句如下:
DECLARE var_name[,varname]...date_type [DEFAULT value ];
如上,var_name
为局部变量名称,DEFAULT value
子句给变量提供一个默认值,值除了可以被声明为一个常数之外,还可以被指定为一个表达式,如果没有DEFAULT
子句,初始值为NULL.
定义变量: 定义名称为myparam
的变量,类型为INT,默认值设置为100
,只能在过程中使用.
DECLARE myparam INT DEFAULT 100 ;DECLARE charsss char DEFAULT 'hello' ;
变量赋值: 定义3个变量,分别为var1,var2,var3
,数据类型为INT,使用SET为变量赋值,代码如下:
DECLARE var1,var2,var3 INT ;MariaDB [lyshark]> set @var1 = 10 ,@var2 = 30 ; Query OK, 0 rows affected (0.01 sec) MariaDB [lyshark]> set @var3 = @var1 + @var2 ; Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> select @var3 ; + | @var3 | + | 40 | + 1 row in set (0.00 sec)
使用数据光标 查询语句可能返回多条记录,如果数据量非常大,需要在存储过程和函数中使用光标来逐条读取查询结果集中的记录,光标必须在声明处理程序之前被声明,并且变量和条件还必须在声明光标或处理程序之前被声明.
声明光标: 声明名称为cursor_lyshark
的光标,SQL代码如下:
declare cursor_lyshark cursor for select Name,Price from lyshark;
打开光标: 打开名称为cursor_lyshark
的光标,SQL代码如下:
使用光标: 使用名称为cursor_lyshark
的光标,将查询出的数据存入lyshark_name
和lyshark_price
这两个变量中.
fetch cursor_lyshark into lyshark_name,lyshark_price;
关闭光标: 关闭名称为cursor_lyshark
的光标文件.
使用流程控制 流程控制语句用来根据条件控制语句的执行,MySQL中用来构造控制流程的语句有:IF,CASE,LOOP,LEAVE,ITERATE,REPEAT,WHILE
等,每个流程中可能包含一个单独的语句,或者是使用BEGIN...END
构造的复合语句,构造可以被嵌套.
IF-THEN-ELSE条件语句: IF语句用来判断条件分支
首先传递一个数值,接收到parameter
变量里,然后自增+1,并判断,如果var=0
则返回系统时间,var=1
则返回系统日期.
CREATE PROCEDURE proc_1(IN parameter int )BEGIN DECLARE var int ; SET var= parameter + 1 ; IF var= 0 THEN select CURRENT_TIME (); ELSEIF var= 1 THEN select CURRENT_DATE (); END IF; END
接着我们编译这段过程,并测试依次传入temp=-1
和temp=1
.
MariaDB [lyshark]> set @temp = 0 ; Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> call proc_1(@temp ); + | CURRENT_DATE () | + | 2018 -12 -28 | + 1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> set @temp = -1 ; Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> call proc_1(@temp ); + | CURRENT_TIME () | + | 07 :23 :04 | + 1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)
CASE-WHEN-THEN-ELSE语句: 另一个进行条件判断的语句,条件判断分支结构
CREATE PROCEDURE proc_2 (IN parameter INT ) BEGIN DECLARE var INT ; SET var= parameter + 1 ; CASE var WHEN 0 THEN select "这个数值是0呀"; WHEN 1 THEN select "这个数值是1呀"; ELSE select "这个数值是其他呀"; END CASE ; END ;
MariaDB [lyshark]> set @temp = 0 ; Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> call proc_2(@temp ); + | 这个数值是1 呀 | + | 这个数值是1 呀 | + 1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> set @temp = -1 ; Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> call proc_2(@temp ); + | 这个数值是0 呀 | + | 这个数值是0 呀 | + 1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> set @temp = -9999 ; Query OK, 0 rows affected (0.00 sec) MariaDB [lyshark]> call proc_2(@temp ); + | 这个数值是其他呀 | + | 这个数值是其他呀 | + 1 row in set (0.00 sec)Query OK, 0 rows affected (0.00 sec)
LOOP语句: 用于循环执行重复语句,LOOP只会创建一个循环过程,并不会判断.
首先使用LOOP语句进行循环操作,id
值小于等于5之前,将重复执行循环过程,代码如下:
CREATE PROCEDURE proc_4() BEGIN DECLARE id INT ; SET id= 0 ; LOOP_LABLE:LOOP SELECT "这里开始计数"; SET id= id+ 1 ; IF id >= 5 THEN LEAVE LOOP_LABLE; #退出循环 END IF; END LOOP; END ;
WHWHILE-DO…END-WHILE语句: 流程循环语句.
CREATE PROCEDURE proc_4() BEGIN DECLARE var INT ; SET var= 0 ; WHILE var< 6 DO select "循环判断"; SET var= var+ 1 ; END WHILE ; END ;
ITERATE语句: 通过引用复合语句的标号,来从新开始复合语句
CREATE PROCEDURE proc_5() BEGIN DECLARE v INT ; SET v= 0 ; LOOP_LABLE:LOOP IF v= 3 THEN SET v= v+ 1 ; ITERATE LOOP_LABLE; END IF; INSERT INTO t VALUES (v); SET v= v+ 1 ; IF v>= 5 THEN LEAVE LOOP_LABLE; END IF; END LOOP; END ;
REPEAT语句: 此语句的特点是执行操作后检查结果
CREATE PROCEDURE proc_6 () BEGIN DECLARE v INT ; SET v= 0 ; REPEAT INSERT INTO t VALUES (v); SET v= v+ 1 ; UNTIL v>= 5 END REPEAT; END ;
查看删除过程 MySQL中,用户可以使用SHOW STATUS语句
或SHOW CREATE语句
来查看存储过程和函数,也可以直接从系统的information_schema
数据库中查询
show status查看存储过程:
MariaDB [lyshark]> show procedure status like 'p%' \G * * * * * * * * * * * * * * * * * * * * * * * * * * * 1. row * * * * * * * * * * * * * * * * * * * * * * * * Db: lyshark Name: proc_1 Type: PROCEDURE Definer: lyshark@% Modified: 2018 -12 -28 21 :16 :26 Created: 2018 -12 -28 21 :16 :26 Security_type: DEFINER Comment: character_set_client: utf8mb4 collation_connection: utf8mb4_general_ci Database Collation : latin1_swedish_ci 12 rows in set (0.00 sec)
show create查看过程与函数:
MariaDB [lyshark]> show create function lyshark.NameZip; + | Function | sql_mode | Create Function | character_set_client | collation_connection | Database Collation | + | NameZip | | CREATE DEFINER= `root`@`localhost` FUNCTION `NameZip`() RETURNS char (50 ) CHARSET latin1return (select s_name from suppliers where s_call= '4521' ) | utf8 | utf8_general_ci | latin1_swedish_ci | +
select 查询存储过程:
MariaDB [lyshark]> select name,created from mysql.proc where db= "lyshark" and type= "PROCEDURE"; + | name | created | + | CountProc | 2018 -12 -28 04 :19 :58 | | CountProc1 | 2018 -12 -28 04 :31 :10 | | Proc | 2018 -12 -28 03 :47 :30 | | proc11111 | 2018 -12 -28 21 :24 :19 | | proc3 | 2018 -12 -28 05 :34 :18 | | proc4 | 2018 -12 -28 05 :37 :10 | | proc8 | 2018 -12 -28 21 :27 :12 | | proc_1 | 2018 -12 -28 07 :20 :08 | | proc_111 | 2018 -12 -28 21 :14 :01 | | proc_1111 | 2018 -12 -28 21 :14 :16 | | proc_2 | 2018 -12 -28 07 :27 :32 | | proc_3 | 2018 -12 -28 07 :35 :11 | | proc_4 | 2018 -12 -28 21 :15 :40 | | proc_444 | 2018 -12 -28 21 :16 :26 | | wang | 2018 -12 -28 04 :19 :07 | | wang1 | 2018 -12 -28 04 :25 :30 | + 16 rows in set (0.00 sec)
select 查询存储函数:
MariaDB [lyshark]> select name,created from mysql.proc where db= "lyshark" and type= "FUNCTION"; + | name | created | + | CountProc2 | 2018 -12 -28 05 :04 :28 | | NameZip | 2018 -12 -28 05 :16 :35 | + 2 rows in set (0.00 sec)
show语句的其他用法:
MariaDB [lyshark]> show procedure status; MariaDB [lyshark]> show function status;
删除过程与函数:
drop procedure lyshark;drop function countproc;