MySQL从1.5版本开始支持存储过程(PROCEDURE)
存储过程将复杂的业务实现(增删改查、变量、数组、分支、循环、方法调用、事务提交、回滚等等
)搬到数据库实现,作为大数据开发者,需要能了解存储过程,如果能掌握甚至可以写一些存储过程则更佳。
在我们进行查询操作的时候,有的时候我们可能会进行重复性的查询工作。例如: 我需要从固定的几张表中查询固定的几个字段的值,可以每次查询的时候传入的条件的值不同,但是查询的表和字段始终没有改变。那么这个时候我们应该怎么去优化这个流程呢?这就可以使用到存储过程来完成了。
存储过程简单来说,就是为以后的使用而保存的一条或多条MySQL语句的集合。可将其视为批件,虽然它们的作用不仅限于批处理。存储过程就是有业务逻辑和流程的集合,可以在存储过程中创建表,更新数据,删除等等。
通过把处理封装在容易使用的单元中,简化复杂的操作(正如前面例子所述)。
由于不要求反复建立一系列处理步骤,这保证了数据的完整性。如果所有开发人员和应用程序都使用同一(试验和测试)存储过程,则所使用的代码都是相同的。这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大。防止错误保证了数据的一致性。
简化对变动的管理。如果表名、列名或业务逻辑(或别的内容)有变化,只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。
-- 常用的结构
-- 如果之前存在这个存储过程,先将其删除。不允许出现两个名字相同的存储过程。
drop procedure if exists `procedure_name`;
-- 设定分隔符
delimiter ;;
-- 创建存储过程
create procedure `procedure_name`(in `a` int, in `b` varchar(20))
begin
-- 存储过程中的逻辑
end;
;;
-- 恢复分隔符
delimiter ;
定义一个存储过程,实现查询两个日期之间入职的员工信息
drop procedure if exists `select_emp_by_hiredate`;
delimiter ;;
create procedure `select_emp_by_hiredate`(in `from_date` date, in `to_date` date)
begin
select * from `emp` where `hiredate` between `from_date` and `to_date`;
end;
;;
delimiter ;
-- 调用存储过程
call `select_emp_by_hiredate`('1981-01-01', '1981-09-01');
MySQL中,变量可以分为局部变量、用户变量、会话变量、全局变量的划分
局部变量一般用在sql语句块中,比如存储过程的begin/end。其作用域仅限于该语句块,在该语句块执行完毕后,局部变量就消失了。
局部变量一般用declare来声明,可以使用default来说明默认值。
drop procedure if exists `test`;
delimiter ;;
create procedure `test`()
begin
declare number int default 0;
select number;
end;
;;
delimiter ;
call `test`();
用户变量的作用域要比局部变量要广。用户变量可以作用于当前整个连接,但是当当前连接断开后,其所定义的用户变量都会消失。
set @变量名
对用户变量赋值有两种方式,一种是直接用"=“号,另一种是用”:=“号。其区别在于使用set命令对用户变量进行赋值时,两种方式都可以使用;当使用select语句对用户变量进行赋值时,只能使用”:=“方式,因为在select语句中,”="号被看作是比较操作符。
drop procedure if exists `test`;
delimiter ;;
create procedure `test`(in `a` int, in `b` int)
begin
set @number1 = 0;
set @number2 := 0;
select @number1:= `a` + `b` as `sum`, @number2 := `a` - `b` as `sub`;
end;
;;
delimiter ;
call `test`(20, 5);
select @number1, @number2;
服务器为每个连接的客户端维护一系列会话变量。在客户端连接时,使用相应全局变量的当前值对客户端的会话变量进行初始化。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,而不能更改其它客户端的会话变量。会话变量的作用域与用户变量一样,仅限于当前连接。当当前连接断开后,其设置的所有会话变量均失效。
-- 设置会话变量有如下三种方式:
set session var_name = value;
set @@session.var_name = value;
set var_name = value;
-- 查看一个会话变量也有如下三种方式:
select @@var_name;
select @@session.var_name;
show session variables like "%var%";
mysql> show session variables;
全局变量影响服务器整体操作。当服务器启动时,它将所有全局变量初始化为默认值。这些默认值可以在选项文件中或在命令行中指定的选项进行更改。要想更改全局变量,必须具有SUPER权限。全局变量作用于server的整个生命周期,但是不能跨重启。即重启后所有设置的全局变量均失效。要想让全局变量重启后继续生效,需要更改相应的配置文件。
要设置一个全局变量,有如下两种方式:
set global var_name = value; //注意:此处的global不能省略。根据手册,set命令设置变量时若不指定GLOBAL、SESSION或者LOCAL,默认使用SESSION
set @@global.var_name = value; //同上
要想查看一个全局变量,有如下两种方式:
select @@global.var_name;
show global variables like "%var%";
mysql> show global variables;
定义存储过程的时候,有三种模式的参数: IN、OUT、INOUT
模式 | 说明 |
---|---|
IN | 调用存储过程的时候,实际参数的值会传递到存储过程内部。对形参进行的修改也不会影响实参。 |
OUT | 调用存储过程的时候,实际参数的值不会传递到存储过程的内部。此时存储过程的形参默认的初始值是NULL。 对形参的修改会影响实际参数的值。 |
INOUT | 复合模式,调用存储过程的时候,实际参数的值会传递到存储过程的内部,对形参的修改也会影响到实际参数的值。 |
drop procedure if exists `parameter_test`;
delimiter ;;
create procedure `parameter_test`(in `a_in` int, out `a_out` int, inout `a_in_out` int)
begin
select a_in, a_out, a_in_out;
set a_in = 100;
set a_out = 100;
set a_in_out = 100;
end;
;;
delimiter ;
set @v_in := 10;
set @v_out := 20;
set @v_in_out := 30;
call parameter_test(@v_in, @v_out, @v_in_out);
select @v_in, @v_out, @v_in_out ;