我们把若干条 SQL 封装起来,起个名字,就叫过程,把此过程存储在数据库中就叫存储过程。
过程:没有返回值的函数;
函数:有返回值的过程。
1、创建语法
create procedure p_name(in name, out age)
begin
...
end;
参数类型:
(1) in 表示只是用来输入;
(2) out 表示只是用来输出;
(3) inout 可以用来输入,也可以用作输出。
调用存储过程:
call p_name('shang', @age);
2、查询存储过程
show procedure status like 'p_name';
show create procedure p_name \G
select * from information_schema.routines where routine_name = 'p1';
3、删除存储过程
drop procedure [if exists] p_name; #删除存储过程需要确保有 alter routine 的相应权限
变量定义:declare var1 [,var2...] var_type [default 默认值];
流程控制:if、case、loop、leave、iterate、repeat、while
总结
优点:
1、执行速度快。因为我们的每个 SQL 语句都需要经过编译,然后再运行,但是存储过程都是直接编译好了之后,直接运行即可;
2、减少网络流量。我们传输一个存储过程比我们传输大量的 SQL 语句的开销要小得多;
3、提高系统安全性。因为存储过程可以使用权限控制,而且参数化的存储过程可以有效地防止 SQL 注入攻击。保证了其安全性;
4、耦合性降低。当我们的表结构发生了调整或变动之后,我们可以修改相应的存储过程,我们的应用程序在一定程度上需要改动的地方就较小了;
5、重用性强。因为我们写好一个存储过程之后,再次调用它只需要一个名称即可,也就是“一次编写,随处调用”,而且使用存储过程也可以让程序的模块化加强。
缺点:
1、移植性差。因为存储过程是和数据库绑定的,如果我们要更换数据库之类的操作,可能很多地方需要改动;
2、修改不方便。因为对于存储过程而言,我们并不能特别有效的调试,它的一些 bug 可能发现的更晚一些,增加了应用的危险性;
3、优势不明显和赘余功能。对于小型 web 应用来说,如果我们使用语句缓存,发现编译 SQL 的开销并不大,但是使用存储过程却需要检查权限一类的开销,这些赘余功能也会在一定程度上拖累性能。
实例:
create procedure p2()
begin
declare total int default 0;
declare num int default 0;
while num <= 100 do
set total := total + num;
set num := num +1;
end while;
select total;
end$
create procedure p3(in n int)
begin
declare total int default 0;
declare num int default 0;
while num <= n do
set total := total + num;
set num := num +1;
end while;
select total;
end$
create procedure p5(in n int,out total int)
begin
declare num int default 0;
set total := 0;
while num <= n do
set total := total + num;
set num := num +1;
end while;
end$
create procedure p6(inout age int)
begin
set age := age + 10;
end$
set @curr_age = 14$
call p6(@curr_age)$
select @curr_age$