什么是存储过程?
存储过程和函数都类似于Java中的方法。存储过程是一组预先编译好的sql指令集合。
预先编译好的,也就意味着,调用存储过程时,不再需要花时间去编译sql语句,直接就可以执行,从而提高效率。
好处:
- 提高代码重用性
- 简化操作
- 提高了效率
存储过程能解决什么问题?
使用存储过程
创建存储过程
语法:
create procedure 存储过程名(参数列表)begin存储过程体(一组sql语句)end
注意点:
- 参数列表包含三部分:参数模式 参数名 参数类型。例如,
in stuname varchar(20) - 参数模式:
IN:表示该参数是输入参数,调用存储过程时,被in修饰的参数必须传入值。OUT:表示该参数可作为输出,即该参数是返回值INOUT:表示该参数即可作为输入参数,又可作为输出(即返回值)。
- 若存储过程体中只有一句 sql 语句,
BEGIN END可省略。 - 存储过程体中的每条sql语句必须以分号结尾。存储过程的结尾可以通过
delimiter进行设置。
语法:
DELIMITER 结束符号-- 如,下面的语句表示以$作为存储过程的结束符DELIMITER $
调用存储过程
call 存储过程名(实参列表);
删除存储过程
drop procedure 存储过名1, 存储过名2,...;
查看存储过程的结构
show create procedure myp2;
存储过程使用实例
空参存储过程
select * from account;-- 将结束符设为$delimiter $-- 创建存储过程create procedure myp1()begininsert into account (username, balance)values ('john', 1000), ('mark', 2000), ('mary', 3000), ('steve', 4000);end $--将结束符还原delimiter ;-- 调用存储过程call myp1();
初始表:
+----+----------+---------+| id | username | balance |+----+----------+---------+| 1 | 张无忌 | 500 || 2 | 赵敏 | 1000 |+----+----------+---------+
执行存储过程后:
+----+----------+---------+| id | username | balance |+----+----------+---------+| 1 | 张无忌 | 500 || 2 | 赵敏 | 1000 || 7 | john | 1000 || 8 | mark | 2000 || 9 | mary | 3000 || 10 | steve | 4000 |+----+----------+---------+
带 IN 模式的存储过程
先举个简单的实例:
select * from account;delimiter $-- 参数列表中的username其实是个局部变量,就跟Java中一样create procedure myp2(in username varchar(20))beginselect * from account where account.username=username;end $delimiter ;call myp2('张无忌');
结果:
MariaDB [myemployees]> call myp2('张无忌');+----+----------+---------+| id | username | balance |+----+----------+---------+| 1 | 张无忌 | 500 |+----+----------+---------+1 row in set (0.004 sec)
再举个复杂的例子(结合了变量概念):例如要用存储过程来实现用户登录成功与否
新建 admin 表:
create table admin (id int primary key auto_increment,username varchar(20) not null,password varchar(20) not null);insert into admin (username, password) values ('admin', '123'), ('hello', '123456');
MariaDB [myemployees]> select * from admin;+----+----------+----------+| id | username | password |+----+----------+----------+| 1 | admin | 123 || 2 | hello | 123456 |+----+----------+----------+2 rows in set (0.000 sec)
创建存储过程:
select * from admin;delimiter $create procedure myp3(in username varchar(20), in password varchar(20))begindeclare result int default 0;select count(*) into resultfrom adminwhere admin.username=username and admin.password=password;select if(result>0, '登录成功', '登录失败');end $delimiter ;call myp3('admin', '123');
思路:查询 admin 表中是否有指定 username 和 password 的记录,若记录数大于 0(这一点通过变量来实现),则意味着登录成功,否则失败。
结果:
MariaDB [myemployees]> call myp3('admin', '123');+--------------------------------------+| if(result>0, '登录成功', '登录失败') |+--------------------------------------+| 登录成功 |+--------------------------------------+1 row in set (0.003 sec)
带 OUT 模式的存储过程
例 1 :只使用一个 OUT 修饰的参数:查询 account 表中,指定 username 对应的 balance
select * from account;delimiter $create procedure myp4(in username varchar(20), out balance varchar(20))beginselect a.balance into balancefrom account awhere a.username=username;end $delimiter ;call myp4('张无忌', @balance);-- 读取out修饰的参数select @balance;
结果:
MariaDB [myemployees]> select @balance;+----------+| @balance |+----------+| 500 |+----------+1 row in set (0.000 sec)
例 2 :使用两个 OUT 修饰的参数:查询 account 表中,指定 username 对应的 balance,以及 balance-1000 后的结果
select * from account;delimiter $create procedure myp5(in username varchar(20), out balance varchar(20), out balance_minus varchar(20))beginselect a.balance, (a.balance-1000) into balance, balance_minusfrom account awhere a.username=username;end $delimiter ;call myp5('张无忌', @balance, @balance_minus);-- 读取out修饰的参数select @balance, @balance_minus;
结果:
MariaDB [myemployees]> select @balance, @balance_minus;+----------+----------------+| @balance | @balance_minus |+----------+----------------+| 500 | -500 |+----------+----------------+1 row in set (0.000 sec)
带 INOUT 模式的存储过程
例子:传入 a 和 b 两个值,返回二者翻倍后的结果
delimiter $create procedure myp6(inout a int, inout b int)beginset a=a*2;set b=b*2;end $delimiter ;set @a:=2, @b:=5;call myp6(@a, @b);select @a, @b;
结果:
MariaDB [myemployees]> select @a, @b;+------+------+| @a | @b |+------+------+| 2 | 5 |+------+------+1 row in set (0.000 sec)MariaDB [myemployees]> call myp6(@a, @b);Query OK, 0 rows affected (0.000 sec)MariaDB [myemployees]> select @a, @b;+------+------+| @a | @b |+------+------+| 4 | 10 |+------+------+1 row in set (0.000 sec)
