Mysql自定义函数和存储过程
自定义函数和存储过程的区别
- 自定义函数不能拥有输出参数,这是因为自定义函数自身就是输出参数;而存储过程可以拥有输出参数
- 自定义函数中必须包含一条return语句,而这条特殊的sql语句不允许在存储过程中出现
- 可以直接对自定义函数进行调用而不需要使用call语句,而对存储过程的调用需要使用call语句
变量作用域
- 内部的变量再其作用域范围内享有更高的优先权,当执行到end时,内部变量消失,此时已经再其作用域外,变量不再可见,但可通过out参数或者将其指派给会话变量来保存其值
DELIMITER
- 声明语句结束符,如:
- DELIMITER $$
- DELIMITER //
存储过程的参数
in 输入参数
- 表示调用者向过程传入值(传入值可以是字面量或变量)
示例:
delimiter $$
create procedure in_param(in p_in int)
begin
select p_in;
set p_in=2;
select P_in;
end$$
delimiter ;
## 调用
set @p_in=1;
call in_param(@p_in);
## 输出结果
1
2
## 调用
select @p_in;
## 输出结果
1
## 说明:p_in 在存储过程中被修改,但并不影响 @p_id 的值,因为前者为局部变量、后者为全局变量
out 输出参数
- 表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)
示例:
delimiter //
create procedure out_param(out p_out int)
begin
select p_out;
set p_out=2;
select p_out;
end//
delimiter ;
## 调用
set @p_out=1;
call out_param(@p_out);
## 输出
null
2
## 说明:因为out是向调用者输出参数,不接收输入的参数,所以存储过程里的p_out为null
## 调用
select @p_out;
## 输出结果
2
## 说明:调用了out_param存储过程,输出参数,改变了p_out变量的值
inout输入输出参数
- 既表示调用者向过程传入值,又表示过程向调用者传出值(值只能是变量),改类型的参数应尽量少用
示例:
delimiter $$
create procedure inout_param(inout p_inout int)
begin
select p_inout;
set p_inout=2;
select p_inout;
end$$
delimiter ;
## 调用
set @p_inout=1;
call inout_param(@p_inout);
## 输出结果
1
2
## 调用
select @p_inout;
## 输出结果
2
## 说明:调用了inout_param存储过程,接受了输入的参数,也输出参数,改变了变量
- 注意
- 如果过程没有参数,也必须在过程名后面写上小括号例
- 确保参数的名字不等于列的名字,否则在过程体中,参数名被当做列名来处理
MySql控制语句
存储过程体控制语句
begin-end
条件语句
if-then-else语句
语句格式
if 条件 then
动作
end if;
if 条件 then
动作
else
动作
end if;
示例代码
DELIMITER //
CREATE PROCEDURE proc2(IN parameter int)
begin
declare var int;
set var=parameter+1;
if var=0 then
insert into t values(17);
end if;
if parameter=0 then
update t set s1=s1+1;
else
update t set s1=s1+2;
end if;
end;
//
DELIMITER ;
case语句(类似Java中的switch-case)
语句格式
case 变量
when 条件 then
动作
when 条件 then
动作
else
动作
end case;
- 特别注意
- when中的条件需为值而不能为表达式
- else下如果没有语句,则else须不保留
示例代码
DELIMITER //
CREATE PROCEDURE proc3 (in parameter int)
begin
declare var int;
set var=parameter+1;
case var
when 0 then
insert into t values(17);
when 1 then
insert into t values(18);
else
insert into t values(19);
end case;
end;
//
DELIMITER ;
循环语句
while-end while(类似Java中的while语法)
语句格式
while 条件 do
动作
end while
示例代码
DELIMITER //
CREATE PROCEDURE proc4()
begin
declare var int;
set var=0;
while var<6 do
insert into t values(var);
set var=var+1;
end while;
end;
//
DELIMITER ;
repeat-end repeat(类似Java中的do-while语法)
语句格式
repeat
动作
until 条件
end repeat;
示例代码
DELIMITER //
CREATE PROCEDURE proc5 ()
begin
declare v int;
set v=0;
repeat
insert into t values(v);
set v=v+1;
until v>=5 end repeat;
end;
//
DELIMITER ;
loop-end loop(类似Java中的for循环语句,其中的leave类似Java中的break语句)
语句格式
loop
动作
leave --注意,此处的leave通常跟标签一起结合使用,如:leave Loop_lable
end loop;
示例代码
DELIMITER //
CREATE PROCEDURE proc6 ()
begin
declare v int;
set v=0;
LOOP_LABLE:loop
insert into t values(v);
set v=v+1;
if v >=5 then
leave LOOP_LABLE;
end if;
end loop;
end;
//
DELIMITER ;
iterate迭代(类似Java中的continue语句)
- iterate通过引用复合语句的标号来重新开始复合语句
示例代码
DELIMITER //
CREATE PROCEDURE proc10 ()
begin
declare v int;
set v=0;
LOOP_LABLE:loop
if v=3 then
set v=v+1;
ITERATE LOOP_LABLE;
end if;
insert into t values(v);
set v=v+1;
if v>=5 then
leave LOOP_LABLE;
end if;
end loop;
end;
//
DELIMITER ;
Mysql函数
定义函数的格式一
CREATE FUNCTION 函数名(参数 类型,[参数 类型,...])
RETURNS 返回类型 RETURN 表达式值
-- 注意
-- 这种方式不能使用任何SQL语句
示例如下
-- 1. 创建函数
create function fun_add(a int,b int)
returns int return a + b;
-- 2. 执行函数
select fun_add(1,1);
定义函数的格式二
CREATE FUNCTION 函数(参数 类型,[参数 类型,...])
RETURNS 返回类型
BEGIN
END;
-- 如果要在函数体中可以使用更为复杂的语法,比如复合结构/流程控制/任何SQL语句/定义变量等。带复合结构的函数体的自定义函数的
示例如下
CREATE FUNCTION uuid_32() RETURNS CHAR(32)
BEGIN
RETURN replace(uuid(), '-', '');
END;
Mysql游标
游标定义
- 游标是一个存储在MySQL服务器上的数据库查询,它不是一条select语句,而是被该语句所检索出来的结果集。
使用游标的步骤
- 声明游标:这个过程实际上是没有遍历数据的,它只是定义要使用的select语句来获取数据
- 打开游标:游标定义好后,那么这里就需要打开游标。这个过程用前面定义的select语句把数据实际检索出来。即这个步骤之后,我们就可以遍历游标中的数据了
- 遍历数据:对于有数据的游标,根据需要取出各行的数据来进行一定的操作
- 关闭游标:使用完游标后,一定要关闭游标
游标使用的语法
- 声明游标
DECLARE cursor_name CURSOR FOR select_statement;
- 打开游标
OPEN cursor_name;
- 遍历数据
FETCH cursor_name INTO var_name ;
- 关闭游标
CLOSE cursor_name ;
应用举例
delimiter $ # 申明结束标志
drop procedure if exists StatisticStore$ # 如果存储过程已经存在则删除
CREATE PROCEDURE StatisticStore()
BEGIN
# 创建接收游标数据的变量
declare c int; # 获取单条纪录的数量
declare n varchar(20); #获取名称
# 创建总数变量
declare total int default 0;
# 创建结束标志变量
declare done int default false;
# 创建游标 获取name和count的集合
declare cur cursor for select name,count from store where name = 'iphone';
# 指定游标循环结束时的返回值
declare continue HANDLER for not found set done = true;
# 设置初始值
set total = 0;
# 打开游标
open cur;
# 开始循环游标里的数据
read_loop:loop
# 根据游标当前指向的一条数据 插入到上面申明的局部变量中
fetch cur into n,c;
# 判断游标的循环是否结束
if done then
leave read_loop; # 跳出游标循环
end if;
# 获取一条数据时,将count值进行累加操作,这里可以做任意你想做的操作,
set total = total + c;
# 有loop 就一定要有end loop
end loop;
# 关闭游标
close cur;
# 输出结果
select total;
END
$
delimiter ;
# 调用存储过程
call StatisticStore();