MySQL学习笔记之MySQL存储过程
一、存储过程简介
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;