一、存储过程简介

SQL语句需要先编译再执行,而存储过程(stored procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名称并给定参数(若该存储过程带有参数)来调用执行。

一个存储过程是一个可编程的函数,在数据库中创建并保存,可以SQL语句和一些特殊控制结构组成。当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,允许控制数据的访问方式。

存储过程通常有一下优点:

1)增强SQL语言的功能和灵活性。存储过程可以用流程控制语句编写,有很强的的灵活性,可以完成复杂的判断和较复杂的运算。

2)标准组件式编程。存储过程被创建后,可以在程序中被多次调用,而不必再重新编写该存储过程的SQL语句。而且数据专业人员可以随时对存储过程进行修改,对应用程序源代码毫无影响。

3)实现较快的执行速度。如果某一操作包含大量的transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并给出最终被存储在系统表中的执行计划。而批处理的transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。

4)减少网络流量。针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的transaction-SQL语句被组织成存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大减少了网络流量并降低了网络负载。

5)作为一种安全机制来充分利用。系统管理员通过执行某一存储过程的权限进行限制,能够实现对相应数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。

存储过程思想上很简单,就是数据库SQL语言层面的代码封装与重用。

二、MySQL的存储过程

MySQL5.0版本开始支持存储过程。大大提高了数据库的处理速度,同时也提高了数据库编程的灵活性。

三、MySQL存储过程创建

语法:

delimiter $$#临时修改SQL语句的结束符,可以自己定义

CREATE

[DEFINER = { user | CURRENT_USER }] #指定创建存储过程的用户

PROCEDURE sp_name ([存储过程参数[,...]]) #声明存储过程

BEGIN#存储过程体开始

存储过程体

END #存储过程体结束

delimiter; #存储过程创建完成,修改回结束符

注:

1)MySQL默认的结束符是';',在创建存储过程时存储过程体中使用';',将会导致存储过程编译过程报错,所以需要先临时修改MySQL的结束符。

2)存储过程的参数格式:

[in | out | inout] 参数名 参数类型

3)存储过程体使用BEGIN和END标识(BEGIN...END可以嵌套使用)。

例:创建一个删除学生年龄为null的存储过程

mysql> select * from students;

+----+-----------+--------+------+

| id | name | gender | age |

+----+-----------+--------+------+

| 2 | 李四 | 1 | 19 |

| 3 | 周芷若 | 2 | 18 |

| 4 | 赵敏 | 2 | 18 |

| 5 | Lucy | 2 | 19 |

| 6 | Tony | 1 | 20 |

| 7 | Lucy | 2 | 20 |

| 8 | Tom | 2 | NULL |

| 9 | Tom | 2 | NULL |

| 11 | Lily | 2 | NULL |

| 12 | Tomy | 2 | NULL |

| 13 | ZhangSan | 2 | NULL |

| 21 | LiLei | 2 | NULL |

| 31 | LiLei | 2 | NULL |

| 33 | 令狐冲 | 1 | NULL |

| 34 | 王语嫣 | 2 | NULL |

| 35 | 小红 | 2 | NULL |

+----+-----------+--------+------+

16 rows in set (0.06 sec)

mysql> delimiter $$

mysql> create procedure delete_null_age_stu()

-> begin

-> delete from students where age is null;

-> end $$

Query OK, 0 rows affected (0.05 sec)

mysql> delimiter ;

mysql> call delete_null_age_stu();

Query OK, 10 rows affected (0.20 sec)

mysql> select * from students;

+----+-----------+--------+------+

| id | name | gender | age |

+----+-----------+--------+------+

| 2 | 李四 | 1 | 19 |

| 3 | 周芷若 | 2 | 18 |

| 4 | 赵敏 | 2 | 18 |

| 5 | Lucy | 2 | 19 |

| 6 | Tony | 1 | 20 |

| 7 | Lucy | 2 | 20 |

+----+-----------+--------+------+

6 rows in set (0.00 sec)

四、存储过程的参数

MySQL存储过程的参数用在存储过程的定义,共有三种参数类型,IN,OUT,INOUT,形式如:

CREATEPROCEDURE 存储过程名([[IN |OUT |INOUT ] 参数名 数据类形...])

1)IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量)

例:创建存储过程根据传入的参数插入学生信息表

delimiter $$

create procedure insert_students(in stu_name varchar(30),in stu_gender int,in stu_age int)

begin

insert into students(name,gender,age) values(stu_name,stu_gender,stu_age);

end $$

delimiter ;

call insert_students('萧峰',1,20);

mysql> select * from students;

+----+-----------+--------+------+

| id | name | gender | age |

+----+-----------+--------+------+

| 2 | 李四 | 1 | 19 |

| 3 | 周芷若 | 2 | 18 |

| 4 | 赵敏 | 2 | 18 |

| 5 | Lucy | 2 | 19 |

| 6 | Tony | 1 | 20 |

| 7 | Lucy | 2 | 20 |

| 37 | 萧峰 | 1 | 20 |

+----+-----------+--------+------+

7 rows in set (0.00 sec)

2)OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)

例:创建存储过程,根据传入的学生姓名,科目名称,获取该学生该科目的成绩

mysql> delimiter $$

mysql> create procedure get_students_score(in name varchar(30),in subject varchar(20), out score int)

-> begin

-> select s.score into score from students stu left join score s on stu.id = s.student_id left join subject su on s.subject_id = su.id where stu.name=name and su.name=subject;

-> end $$

Query OK, 0 rows affected (0.25 sec)

mysql> delimiter ;

mysql> call get_students_score('周芷若','语文',@score);

Query OK, 1 row affected (0.00 sec)

mysql> select @score;

+--------+

| @score |

+--------+

| 90 |

+--------+

1 row in set (0.00 sec)

3)INOUT 输入输出参数:既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量)

例:创建存储过程,传入两个值,返回两个值的2倍和2倍后的总和

mysql> delimiter $$

mysql> create procedure inout_param(inout x int,inout y int,out sum int)

-> begin

-> set x = x*2;

-> set y = y*2;

-> set sum = x+y;

-> end $$

Query OK, 0 rows affected (0.11 sec)

mysql> delimiter ;

mysql> set @m = 10;

Query OK, 0 rows affected (0.00 sec)

mysql> set @n = 20;

Query OK, 0 rows affected (0.00 sec)

mysql> call inout_param(@m,@n,@sum);

Query OK, 0 rows affected (0.00 sec)

mysql> select @m,@n,@sum;

+------+------+------+

| @m | @n | @sum |

+------+------+------+

| 20 | 40 | 60 |

+------+------+------+

1 row in set (0.00 sec)

五、删除存储过程

语法:

drop procedure 存储过程名称 # 存储过程每次只能删除一个

六、查看存储过程

语法:

show create procedure 存储过程名

查看所有的存储过程:

show procedure status;