MySQL 存储过程概念及实例

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 语句会将参数名看作列名,从而引发不可预知的结果。
  • 过程体
    • 存储过程的主体部分,也称为存储过程体,包含在过程调用的时候必须执行的 SQL 语句。
    • BEGINEND 关键字
      • 这个部分以关键字 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();