存储过程有哪些特征?
存储过程有哪些优点?
存储过程有哪些缺点?
MySQL中存储结构的语法
delimiter 自定义结束符号
create procedure 储存名([ in ,out ,inout ] 参数名 数据类形...)
beginsql语句
end 自定义的结束符合
delimiter ;
一个简单的MySQL存储结构的例子
delimiter $$
create procedure proc01()
beginselect empno,ename from emp;
end $$
delimiter ;-- 调用存储过程
call proc01();
delimiter简介
delimiter是MySQL分隔符,在MySQL客户端中分隔符默认是分号(;)。如果一次输入的语句较多,并且语句中间有分号,这时需要新指定一个特殊的分隔符。
其实就是告诉mysql解释器,该段命令是否已经结束了,mysql是否可以执行了。默认情况下,delimiter是分号;。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。
在MySQL中,变量分为以下几种:
在MySQL可以通过使用 SELECT…INTO 语句为变量赋值。其基本语法如下:
select col_name [...] into var_name[,...]
from table_name wehre condition 其中:
col_name 参数表示查询的字段名称;
var_name 参数是变量的名称;
table_name 参数指表的名称;
condition 参数指查询条件。
注意:当将查询结果赋值给变量时,该查询语句的返回结果只能是单行单列。
局部变量由用户自定义,在begin/end块中有效。
语法
语法: 声明变量 declare var_name type [default var_value];
举例:declare nickname varchar(32);
例子
delimiter $$
create procedure proc02()
begindeclare var_name01 varchar(20) default ‘aaa’; -- 定义局部变量set var_name01 = ‘zhangsan’; select var_name01;
end $$
delimiter ;
-- 调用存储过程
call proc02();
用户自定义,当前会话(连接)有效。类比java的成员变量 。
语法
语法:
@var_name
不需要提前声明,使用即声明
例子
delimiter $$
create procedure proc04()
beginset @var_name01 = 'ZS';
end $$
delimiter;
call proc04() ;
select @var_name01 ; --可以看到结果
全局语法
语法:
@@global.var_name
全局例子
-- 查看全局变量
show global variables;
-- 查看某全局变量
select @@global.auto_increment_increment;
-- 修改全局变量的值
set global sort_buffer_size = 40000;
set @@global.sort_buffer_size = 40000;
会话变量语法
语法:
@@session.var_name
会话变量例子
-- 查看会话变量
show session variables;
-- 查看某会话变量
select @@session.auto_increment_increment;
-- 修改会话变量的值
set session sort_buffer_size = 50000;
set @@session.sort_buffer_size = 50000 ;
在存储过程中,参数分为in、out和inout三种:
in例子
-- 封装有参数的存储过程,可以通过传入部门名和薪资,查询指定部门,并且薪资大于指定值的员工信息
delimiter $$
create procedure dec_param0x(in dname varchar(50),in sal decimal(7,2),)
beginselect * from dept a, emp b where b.sal > sal and a.dname = dname;
end $$delimiter ;
call dec_param0x('学工部',20000);
out例子
-- ---------传出参数:out---------------------------------
use mysql7_procedure;
-- 封装有参数的存储过程,传入员工编号,返回员工名字
delimiter $$
create procedure proc08(in empno int ,out out_ename varchar(50) )
beginselect ename into out_ename from emp where emp.empno = empno;
end $$delimiter ;call proc08(1001, @o_ename);
select @o_ename;
inout例子
-- 传入员工名,拼接部门号,传入薪资,求出年薪
delimiter $$
create procedure proc10(inout inout_ename varchar(50),inout inout_sal int)
beginselect concat(deptno,"_",inout_ename) into inout_ename from emp where ename = inout_ename;set inout_sal = inout_sal * 12;
end $$
delimiter ;
set @inout_ename = '关羽';
set @inout_sal = 3000;
call proc10(@inout_ename, @inout_sal) ;
select @inout_ename ;
select @inout_sal ;
存储过程的流程控制主要以下几种:
IF语句包含多个条件判断,根据结果为TRUE、FALSE执行语句,与编程语言中的if、else if、else语法类似,其语法格式如下:
-- 语法
if search_condition_1 then statement_list_1[elseif search_condition_2 then statement_list_2] ...[else statement_list_n]
end if
IF例子
-- 输入学生的成绩,来判断成绩的级别:
/*score < 60 :不及格score >= 60 , score <80 :及格score >= 80 , score < 90 :良好score >= 90 , score <= 100 :优秀score > 100 :成绩错误
*/
delimiter $$
create procedure proc_12_if(in score int)
beginif score < 60 thenselect '不及格';elseif score < 80thenselect '及格' ;elseif score >= 80 and score < 90then select '良好';elseif score >= 90 and score <= 100then select '优秀';elseselect '成绩错误';end if;
end $$
delimiter ;
call proc_12_if(120)
而CASE是另一个条件判断的语句,类似于编程语言中的switch语法。
-- 语法一(类比java的switch):
case case_valuewhen when_value then statement_list[when when_value then statement_list] ...[else statement_list]
end case
-- 语法二:
casewhen search_condition then statement_list[when search_condition then statement_list] ...[else statement_list]
end case
case例子
-- 语法一
delimiter $$
create procedure proc14_case(in pay_type int)
begincase pay_typewhen 1 then select '微信支付' ;when 2 then select '支付宝支付' ;when 3 then select '银行卡支付';else select '其他方式支付';end case ;
end $$
delimiter ;call proc14_case(2);
call proc14_case(4);
在存储过程中,循环分为以下三种:
- while
- repeat
- loop
而循环控制分为以下两种:
- leave 类似于 break,跳出,结束当前所在的循环
- iterate类似于 continue,继续,结束本次循环,继续下一次
while语法
【标签:】while 循环条件 do循环体;
end while【 标签】;
while例子:
-- -------存储过程-while
delimiter $$
create procedure proc16_while1(in insertcount int)
begindeclare i int default 1;-- label是一个标签,也就是这个循环的名称label:while i<=insertcount doinsert into user(uid,username,`password`) values(i,concat('user-',i),'123456');set i=i+1;end while label;
end $$
delimiter ;call proc16_while(10);
-- -------存储过程-while + leave
truncate table user;
delimiter $$
create procedure proc16_while2(in insertcount int)
begindeclare i int default 1;label:while i<=insertcount doinsert into user(uid,username,`password`) values(i,concat('user-',i),'123456');if i=5 then leave label;end if;set i=i+1;end while label;
end $$
delimiter ;call proc16_while2(10);
repeat语法
repeat 循环体;
until 条件表达式
end repeat [标签];
repeat例子
-- -------存储过程-循环控制-repeat (优点像while do)
use mysql7_procedure;
truncate table user;delimiter $$
create procedure proc18_repeat(in insertCount int)
begindeclare i int default 1;label:repeatinsert into user(uid, username, password) values(i,concat('user-',i),'123456');set i = i + 1;-- 循环结束条件until i > insertCountend repeat label;select '循环结束';
end $$
delimiter ;call proc18_repeat(100);
loop语法
loop循环体;if 条件表达式 then leave [标签]; end if;
end loop;
loop例子
-- -------存储过程-循环控制-loop
truncate table user;delimiter $$
create procedure proc19_loop(in insertCount int)
begindeclare i int default 1;label:loopinsert into user(uid, username, password) values(i,concat('user-',i),'123456');set i = i + 1;if i > 5 then leave label;end if;end loop label;select '循环结束';
end $$
delimiter ;call proc19_loop(10);
**游标(cursor)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用光标对结果集进行循环的处理。**光标的使用包括光标的声明、OPEN、FETCH 和 CLOSE.
游标语法
-- 声明语法
declare cursor_name cursor for select_statement
-- 打开语法
open cursor_name
-- 取值语法
fetch cursor_name into var_name [, var_name] ...
-- 关闭语法
close cursor_name
而句柄是MySql存储过程提供的对异常处理的功能
句柄语法:
DECLARE handler_action HANDLERFOR condition_value [, condition_value] ...statementhandler_action: {CONTINUE -- 程序继续。| EXIT -- 开始的执行终止... END复合语句,其中处理程序是 宣布。即使条件发生在 内块。| UNDO -- 暂不支持
}condition_value: {mysql_error_code| condition_name -- MySQL 错误代码或 SQLSTATE 值| SQLWARNING -- SQL警告| NOT FOUND -- 没有找到| SQLEXCEPTION -- SQL异常
⚠️⚡特别注意:
在语法中,变量声明、游标声明、handler声明是必须按照先后顺序书写的,否则创建存储过程出错。
例子
use mysql7_procedure;
drop procedure if exists proc21_cursor_handler;
-- 需求:输入一个部门名,查询该部门员工的编号、名字、薪资 ,将查询的结果集添加游标
delimiter $$
create procedure proc20_cursor(in in_dname varchar(50))
begin-- 定义局部变量declare var_empno int;declare var_ename varchar(50);declare var_sal decimal(7,2);declare flag int default 1; -- ----------------------- 声明游标declare my_cursor cursor forselect empno,ename,salfrom dept a, emp bwhere a.deptno = b.deptno and a.dname = in_dname;-- 定义句柄,当数据未发现时将标记位设置为0declare continue handler for NOT FOUND set flag = 0; -- 打开游标open my_cursor;-- 通过游标获取值label:loopfetch my_cursor into var_empno, var_ename,var_sal;-- 判断标志位,如果为0证明已经出现了异常if flag = 1 thenselect var_empno, var_ename,var_sal;elseleave label;end if;end loop label;-- 关闭游标close my_cursor;
end $$;delimiter ;
call proc21_cursor_handler('销售部');
存储函数是什么?
MySQL存储函数(自定义函数),函数一般用于计算和返回一个值,可以将经常需要使用的计算或功能写成一个函数。
存储函数和存储过程一样,都是在数据库中定义一些 SQL 语句的集合。
语法
create function func_name ([param_name type[,...]])
returns type
[characteristic ...]
beginroutine_body
end;
参数说明:
例子
create database mydb9_function;
-- 导入测试数据
use mydb9_function;
-- mysql8.0有可能无法创建存储函数,加了这个就可以了
set global log_bin_trust_function_creators=TRUE; -- 信任子程序的创建者-- 创建存储函数-没有输输入参数
drop function if exists myfunc1_emp;delimiter $$
create function myfunc1_emp() returns int
begindeclare cnt int default 0;select count(*) into cnt from emp;return cnt;
end $$
delimiter ;
-- 调用存储函数
select myfunc1_emp();
-- 创建存储过程-有输入参数drop function if exists myfunc2_emp;
delimiter $$
create function myfunc2_emp(in_empno int) returns varchar(50)
begindeclare out_name varchar(50);select ename into out_name from emp where empno = in_empno;return out_name;
end $$
delimiter ;select myfunc2_emp(1008);
参考:
- MySQL中的存储过程(详细篇)_星辰与晨曦的博客-CSDN博客_mysql存储过程
- MySQL中delimiter关键字的使用_pan_junbiao的博客-CSDN博客_delimiter用法
- 2022新版黑马程序员MySQL知识精讲+mysql实战案例_零基础mysql数据库入门到高级全套教程