1.什么存储过程呢?
官方说明:
存储过程(Stored Procedure)是:在大型数据库系统中,一组为了完成特定功能的SQL语句集,
它存储在数据库中,一次编译后永久有效,用户通过指定的存储过程名称并填写参数(如果有参数
的存储过程)来进行调用,存储过程是数据库中的一个重要对象。
####个人理解:将复杂的SQL语句进行封装,并通过预编译处理,方便代码的重用。
由于通过预编译处理,调用时性能更快。
2.创建存储过程
- 准备阶段
打开MySQL数据创建数据库并添加user表并插入数据如图所示: - 创建存储过程
**语法:**
DELIMITER //
CREATE PROCEDURE 存储过程名称(输入参数,输出参数,输入输出参数)
BEGIN
DECLARE a int; /*声明变量 a,b*/
DECLARE b int;
SET a=1; /*给变量赋值,另一种方式是通过输入参数给变量赋值*/
SET b=2;
--------需要执行的SQL语句
END //
DELIMITER ;
@@@注:
a.分隔符:DELIMITER //............DELIMITER ; 是将存储过程作为一个整体存储到
数据库,因为SQL数据库中使分隔符“;”来表示语句的结束,直接采用“;”,该语句会被当作SQL语句来执行,
所以在存储过程中使用“//”表示分隔符,语句不会被立即执行,在最后使用“DELIMITER ;”来还原分隔符。
b.参数:存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用","分割开,共有三种参数类型,IN,OUT,INOUT:
IN参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
OUT:该值可在存储过程内部被改变,并可返回,就是将读取到数据储到这个参数中。
INOUT:调用时指定,并且可被改变和返回,输入一个参数条件并返回读取到数据。
c.过程体:过程体的开始与结束使用BEGIN与END进行标识。
例如:无参的存储过程
mysql> DELIMITER //
mysql> CREATE PROCEDURE notest()
-> BEGIN
-> SELECT *FROM user where id = 1;
-> END //
Query OK, 0 rows affected (0.04 sec)
mysql> DELIMITER ;
查看存储过程详细信息:\G是将结果竖着显示
mysql> show create procedure test\G;
结果如下:
*************************** 1. row ***************************
Procedure: test
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER=`root`@`localhost` PROCEDURE `test`(in i int,OUT s TEXT,out a text)
BEGIN
SELECT username,age into s,a FROM user WHERE id = i;
END
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: utf8_general_ci
1 row in set (0.00 sec)
ERROR:
No query specified
调用存储过程:
mysql> call notest();
结果如下:
+----+----------+------+------+--------+--------+
| id | username | pwd | age | salary | status |
+----+----------+------+------+--------+--------+
| 1 | 老大 | 123 | 20 | 800 | 正常 |
+----+----------+------+------+--------+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
删除存储过程:
mysql> drop procedure test;
Query OK, 0 rows affected (0.03 sec)
如图所示:
不知道游标的可以学习一下:
有参的存储过程:
DELIMITER //
CREATE PROCEDURE test(in s text,out n varchar(50),inout c varchar(50))
BEGIN
declare done int default false;
declare cur cursor for SELECT username,age FROM user WHERE status = s and age>c;
declare continue HANDLER for not found set done = true;
open cur;
read_loop:loop
fetch cur into n,c;
if done then
leave read_loop;
end if;
end loop;
close cur;
select n,c;
END //
DELIMITER ;
创建完成之后,设置参数:
mysql> set @a='正常',@b='',@c='18';
Query OK, 0 rows affected (0.00 sec)
传入参数调用:
mysql> call test(@a,@b,@c); ;
+--------+------+
| n | c |
+--------+------+
| 老二 | 19 |
+--------+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
@@@注:我这里使用游标循环调用call test(@a,@b,@c);该方法,因为存储过程每次只显示一行数据,
所以进行多次调用。
如图所示:
- 例子:使用存储过程实现 购物(这个很有价值可以学习一下)
DELIMITER //
create procedure buy1(in pidn int,in uidn int,in numn int)
begin
declare jiage float(7,2) default 0.00;
declare zongjia float(9,2) default 0.00;
declare e tinyint(1) default 0;
declare continue handler for SQLEXCEPTION set e=1;
-- 获取价格
select price into jiage from productn where pid=pidn;
-- 算出总价
set zongjia=jiage*numn;
-- 开启事务
start transaction;
-- 扣款
update usern set money=money-zongjia where uid=uidn;
-- 出库
update productn set num=num-numn where pid=pidn;
-- 判断是否有异常
if e=1 then
rollback;
select 0 as re;
else
commit;
select 1 as re;
end if;
end//
DELIMITER ;