什么是存储过程?为什么要用存储过程?
存储过程是具有名字的一段代码,完成一个特定的功能。存储过程保存在数据字典中
1.执行时简单(名字+参数)
2.存储过程中可以有一个、多个SQL语句
使用场景:(Mysql存储过程相对功能较弱)
1.将重复性很高的一些操作,封装到一个存储过程中,简化了对这些SQL的调用
2.批量处理 sql+循环
3.统一接口
语法:
delimiter $$-------定义结束标志,delimiter是分隔符的意思
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body------------------------(过程体)
proc_parameter:
[ IN | OUT | INOUT ] param_name type
end $$
delimiter ;--------最后将结束标志改为分号
characteristic:
COMMENT 'string'
| LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
存储过程参数(in、out、inout)
1.需要输入------in参数
值 --100、赋值的变量 --set @xv=100; @xv
mysql> DELIMITER $$
mysql> CREATE PROCEDURE cou1(IN NAME VARCHAR(2))
-> BEGIN
-> SELECT dept_no FROM departments WHERE dept_name=NAME;
-> END $$
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> call cou1('b');
+---------+
| dept_no |
+---------+
| 1002 |
+---------+
mysql> set @name='b';
Query OK, 0 rows affected (0.00 sec)
mysql> call cou1(@name);
+---------+
| dept_no |
+---------+
| 1002 |
+---------+
2.需要输出------out参数(输出自己想要的参数,因此需要定义某个变量来接收)
变量就可以,可以没有赋值。如果是赋值的话旧值会被覆盖 --@xv;
mysql> DELIMITER $$
mysql> CREATE PROCEDURE cou2(OUT COUNT INT)
-> BEGIN
-> SELECT COUNT(1) INTO COUNT FROM departments;
-> END $$
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> call cou2(@num);
Query OK, 1 row affected (0.00 sec)
mysql> select @num;
+------+
| @num |
+------+
| 4 |
+------+
3.既需要输入,也会有输出----------inout参数
只能是赋值的变量 --set @xv=100; @xv
mysql> delimiter $$
mysql> create procedure cou2(inout d int)
-> begin
-> select count(*) into d from TENNIS.MATCHES where TEAMNO=d;
-> end $$
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> set @e=1;
Query OK, 0 rows affected (0.00 sec)
mysql> call cou2(@e);
Query OK, 1 row affected (0.00 sec)
mysql> select @e;
+------+
| @e |
+------+
| 8 |
+------+
1 row in set (0.00 sec)
一个存储过程如果想要有返回值:
1.out参数
2.inout参数
3.在存储过程内部定义用户变量(内部定义,外部可见)
变量以及赋值
1.set语法
可以给用户变量和局部变量赋值
内外都可以使用,但是只能是单行单列
2.select into给局部变量赋值
- 很经典的一个方式,将SQL返回的多列单行数据赋值给相应变量(一个列对应一个变量)
select name1,name2,name3 into c1,c2,c3
- 这些变量经常是out参数
- 也就是变相的将select的结果传输出了存储过程,让外面的程序可见
3.用户变量(@变量名)
随处可以定义,随处可以使用(定义用户变量@a,在使用过程中也必须使用@a,你能使用a,因为a是局部变量)
不定义可以使用
内部定义,外部可见,一直被保存
4.局部变量(只有名字,没有@符号)
先定义,再使用、只在存储过程内部看见、紧挨着begin下面
begin
declare 变量名 类型 [default value]
变量的作用域(越靠前的begin越看到的变量越少------外层的看不到内层,内层的可以看到外层,并行互相看不到)
变量的作用域就是变量能正常使用而不出错的程序块的范围。在嵌套块的情况下,在外部块中声明的变量可以在内部块中直接使用,而在内部块中声明的变量只能在内部块中使用(在下图中,变量v2只能用在内部块b2中,因此,块b3中的set语句(SET V1=V2)和最后一条set语句(SET V2=100)都是错误的)
if条件判断
Syntax:
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
case条件判断
语法一:
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
语法二:
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list] END CASE
注意点:
如果没有一个when子句的比较结果为true,并且没有写else部分,那么就跑出异常:'Case NOT FOUND FOR CASE statement'.
所以对于单分支没有else的,或者多分支没有else的条件语句,建议用if条件判断
练习题:
1、计算输入的任意两个数之间的连续和,例如:输入1,100,过程实现1+2+3+4.。。。+100的和输出的变量中。a<b
DROP PROCEDURE IF EXISTS sum_proc;
DELIMITER $$
CREATE PROCEDURE sum_proc(IN number1 INT,IN number2 INT,OUT sum_number INT)
BEGIN
SET sum_number=number1;
WHILE number1 < number2
DO
SET number1=number1+1;
SET sum_number=sum_number+number1;
END WHILE;
END $$
DELIMITER ;
CALL sum_proc(1,100,@a);
SELECT @a;
2、计算输入的任意两个数之间偶数的和,且打印出一共和计算了多少次?a<b
DROP PROCEDURE IF EXISTS oushu_proc;
DELIMITER $$
CREATE PROCEDURE oushu_proc(IN number1 INT,IN number2 INT,OUT sum_number INT,OUT coun INT)
BEGIN
SET sum_number=0;
SET coun=0;
WHILE number1 <= number2
DO
SET @yushu=number1%2;
IF @yushu=0
THEN
SET coun=coun+1;
SET sum_number=sum_number+number1;
END IF;
SET number1=number1+1;
END WHILE;
END $$
DELIMITER ;
CALL oushu_proc(2,8,@b,@c);
SELECT @b,@c;
3、计算任意两个数之间,是5的倍数,但不是6的倍数之间的和,且打印出一共计算了多少次?
注意:任意输入的两个数字是否满足条件: a<b
DROP PROCEDURE IF EXISTS beishu_proc;
DELIMITER $$
CREATE PROCEDURE beishu_proc(IN number1 INT,IN number2 INT,OUT sum_number INT,OUT coun INT)
BEGIN
SET sum_number=0;
SET coun=0;
WHILE number1 <= number2
DO
SET @yushu=number1%5;
SET @yushu1=number1%6;
IF @yushu=0 && @yushu1 !=0
THEN
SET sum_number=sum_number+number1;
SET coun=coun+1;
END IF;
SET number1=number1+1;
END WHILE;
END $$
DELIMITER ;
CALL beishu_proc(5,6,@d,@e);
SELECT @d,@e;