1. 存储过程的概念
存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来调用存储过程。
2. 存储过程的价值
2.1. 效率高
存储过程编译一次后,就会存到数据库,每次调用时都直接执行。而普通的sql语句我们要保存到其他地方(例如:记事本上),都要先分析编译才会执行。所以想对而言存储过程效率更高。
2.2. 降低网络流量
存储过程编译好会放在数据库,我们在远程调用时,不会传输大量的字符串类型的sql语句。
2.3. 复用性高
存储过程往往是针对一个特定的功能编写的,当再需要完成这个特定的功能时,可以再次调用该存储过程。
2.4. 可维护性高
当功能要求发生小的变化时,修改之前的存储过程比较容易,花费精力少。
2.5. 安全性高
完成某个特定功能的存储过程一般只有特定的用户可以使用,具有使用身份限制,更安全。
3. 创建存储过程
在创建存储过程时,必须具有 CREATE ROUTINE 权限。
3.1. CREATE PROCEDURE 语法
CREATE PROCEDURE <过程名> ( [过程参数[,…] ] )
<过程体>
[过程参数[,…] ] 格式
[ IN | OUT | INOUT ] <参数名> <类型>
- 过程名
- 存储过程的名称,默认在当前数据库中创建。 若需要在特定数据库中创建存储过程,则要在名称前面加上数据库的名称,即 db_name.sp_name。
- 过程参数
- 存储过程的参数列表。
其中,<参数名>为参数名,<类型>为参数的类型(可以是任何有效的 MySQL 数据类型)。
当有多个参数时,参数列表中彼此间用逗号分隔。
存储过程可以没有参数(此时存储过程的名称后仍需加上一对括号),也可以有 1 个或多个参数。
类型>参数名>
MySQL 存储过程支持三种类型的参数,即输入参数、输出参数和输入/输出参数,分别用 IN、OUT 和 INOUT 三个关键字标识。其中,输入参数可以传递给一个存储过程,输出参数用于存储过程需要返回一个操作结果的情形,而输入/输出参数既可以充当输入参数也可以充当输出参数。
- 注意的是,参数的取名不要与数据表的列名相同,否则尽管不会返回出错信息,但是存储过程的 SQL 语句会将参数名看作列名,从而引发不可预知的结果。
- 存储过程的参数列表。
其中,<参数名>为参数名,<类型>为参数的类型(可以是任何有效的 MySQL 数据类型)。
当有多个参数时,参数列表中彼此间用逗号分隔。
存储过程可以没有参数(此时存储过程的名称后仍需加上一对括号),也可以有 1 个或多个参数。
类型>参数名>
- 过程体
- 存储过程的主体部分,也称为存储过程体,包含在过程调用的时候必须执行的 SQL 语句。
BEGIN
和END
关键字- 这个部分以关键字
BEGIN
开始,以关键字END
结束。 - 若存储过程体中只有一条 SQL 语句,则可以省略
BEGIN-END
标志。 - 在存储过程的创建中,经常会用到一个十分重要的 MySQL 命令,即
DELIMITER
命令。
- 这个部分以关键字
DELIMITER
关键字- 在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的。
- 然而,在创建存储过程时,存储过程体可能包含有多条 SQL 语句,这些 SQL 语句如果仍以分号作为语句结束符,那么 MySQL 服务器在处理时会以遇到的第一条 SQL 语句结尾处的分号作为整个程序的结束符,而不再去处理存储过程体中后面的 SQL 语句,这样显然不行。
- 因此,通常使用 DELIMITER 命令将结束命令修改为其他字符。
- 语法格式如下:
DELIMITER $$
当使用 DELIMITER 命令时,应该避免使用反斜杠“\”字符,因为它是 MySQL 的转义字符。
4. 存储过程实例
4.1. 获取结果
delimiter $$
create procedure testa()
begin
select * from test_table;
end $$
delimiter ;
-- 调用存储过程
call testa;
4.2. 加减法计算
# 创建存储过程
create procedure testpro(in a int,in b int,out sum int)
begin
set sum = a+b;
end;
# 调用存储过程
call testpro(1,2,@s); -- 调用存储过程
select @s; -- 显示过程输出结果
4.3. 变量赋值
# 变量赋值
SET 变量名 = 表达式值 [,variable_name = expression ...]
# 使用变量
use schooldb; -- 使用 schooldb 数据库
create procedure testpro()
begin
declare name varchar(20);
set name = '小明';
select * from studentinfo where studentname = name;
end;
# 调用过程
call testpro();