MySQL常用操作之创建存储过程语法详解
MySQL常用操作之创建存储过程语法详解
- 前言
- 简介
- 语法
- 创建结构
- 变量结构
- 入参变量和出参变量
- 流程控制
- 判断(IF 语句)
- 判断(CASE 语句)
- 循环(LOOP 语句)
- 循环(WHILE 语句)
- 循环(REPEAT 语句)
- 再次循环(ITERATE 语句)
- 总结
- 参考链接
前言
场景介绍
作为一名Java搬运工,实际开发中经常使用定时任务来进行业务批处理,实际上通过数据库存过定时执行也能达到同样的效果。且存在两大好处:
通过修改存储过程的方式修改业务逻辑,不需要重启服务器。
存储过程将每一条SQL语句都进行编译,并保存在数据库当中,那么我们通过Java程序调用SQL语句时可以不用一条条的进行编译,而是直接调用存储过程,效率更高。
简介
概念
存储过程(Stored Procedure)是一种在数据库中存储复杂程序,以便外部程序调用的一种数据库对象,它可以封装成SQL语句集,以便完成一些较为复杂的业务逻辑,并且可以想 Java 等高级编程语言一样输入参数。
存储过程是为了完成特定功能的SQL语句集,创建时会预先编译,并保存在数据库中,用户后续的调用都不需要再次编译了,用户可通过指定存储过程的名字并给定参数(需要时)来调用执行。
存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。
语法
创建结构
创建存过模板
CREATE[DEFINER = { user | CURRENT_USER }]PROCEDURE sp_name ([proc_parameter[,...]])[characteristic ...] routine_body
参数介绍
- proc_parameter参数部分(先写输入/输出参数名,再写参数类型)
[ IN | OUT | INOUT ] param_name type
type 是 MySQL 支持的所有类型,如int、varchar等
routine_body(程序体)部分 ,可以书写合法的SQL语句
BEGIN ...... END$$
声明语句结束符
-- $$ 可以自定义为其他作为结束符DELIMITER $$
声明存储过程
CREATE PROCEDURE nbsp_procedure(IN 参数名 参数类型)
存储过程开始和结束符
BEGIN .... END
创建示例
-- 声明语句结束符,可以自定义:delimiter $$-- 创建存储过程,名为 nbsp_procedure 参数为空, 执行输出 'hello world'create procedure nbsp_procedure () -- 默认当前用户下创建 create definer = `nbsp`@`%` procedure nbsp_procedure ()beginselect 'hello world';end $$-- 声明语句结束符delimiter ;-- 调用存储过程call nbsp_procedure();-- 删除存储过程drop procedure nbsp_procedure;
注意事项
这里需要注意的是 DELIMITER$$ 和 DELIMITER; 两句,DELIMITER是声明分割符的意思,因为MySQL默认以 “;” 为分隔符,如果我们没有声明分割符,那么编译器会把存储过程当成SQL语句进行处理,则存储过程的编译过程会报错,所以要事先用DELIMITER关键字申明当前段分隔符,这样MySQL才会将“;”当做存储过程中的代码,不会执行这些代码,用完了之后要把分隔符还原。
存储过程根据需要可能会有输入、输出、输入输出参数,如果有多个参数用“,”分割开。
过程体的开始与结束使用BEGIN与END进行标识
变量结构
变量分类
MySQL变量一共分为两大类:用户自定义变量和系统变量。
用户自定义变量(重点):局部变量、会话变量
系统变量(理解):会话变量、全局变量
局部变量
用户自定义在begin…end代码块中的,也在代码块中有效。
-- 语法declare 变量名 变量类型 [default 默认值]-- 举例declare name varchar(32) '张三'-- set 赋值delimiter $$drop procedure if exists var01$$create procedure var01()begin-- 声明变量declare username varchar(32) default '张三';-- 为变量赋值set username = '李四';select username;end $$delimiter ;call var01();
会话变量
会话变量即为服务器为每个客户端连接维护的变量。在客户端连接时,使用相应全局变量的当前值对客户端的回话变量进行初始化。
设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量。其作用域与生命周期均限于当前客户端连接。
@username 会话变量可以在 begin … end 代码块中定义,也可以在外部定义,定义后同一变量名在内存中只有一份,且当前会话有效。
delimiter $$drop procedure if exists var02$$-- 创建存储过程create procedure var02()beginset @username='张三';end $$delimiter ;-- 调用存储过程call var02();-- 查询会话变量的值select @username;
入参变量和出参变量
IN 输入变量
表示该参数的值必须在调用存储过程时指定,在存储过程中修改该参数的值不能被返回,为默认值
仅需要将数据传入存储过程,并不需要返回计算后的该值。
只能当做传入参数。
OUT 输出参数
该值可在存储过程内部被改变,并可返回
不接受外部传入的数据,仅返回计算之后的值。
只能当做转出参数。
INOUT输入输出参数
调用时指定,并且可被改变和返回
需要数据传入存储过程经过调用计算后,再传出返回值
可当做传入转出参数。
演示示例
- 创建一个会话变量,用于测试out对会话变量的影响
set @username='wangwu';
- 创建一个var03存过,返回用户名
delimiter $$drop procedure if exists var03$$-- 传入两个变量,第一个为输入in变量,第二个为是输出out变量。当输入用户id 时,返回用户名。create procedure var03(in id int,out username varchar(32))beginselect id,username;-- select 'procedure into username' into username;-- set username='procedure into username'end $$delimiter ;
- 查询会话变量用户名
-- 在还未调用存储过程时,我们发现此时的会话变量@username的值依然为 wangwuselect @username;
- 调用存过,查看会话变量值是否正确
call var03(35,@username);
原因分析:这里就是 in 和 out 参数的区别, 也有区别与Java等高级语言中的参数。
如果是以Java的思想理解调用存储过程的话,我们可能会认为说 @username变量的值为wangwu 传入到 存储过程函数中,所以我们也理所应当的认为 username的值应该为wangwu。
out函数它只负责变量的接收,不负责传入值。 也就是说 调用call var03(35,@username); 的时候,@username只是将它的内存地址传进去,告诉存储过程说,等等你把out变量username的值给我(我是@username)。然后在存储过程中一直都没有给username进行赋值的操作,所以此时的username的值为null,最终就将null赋值给了 @username。
- 查询会话变量用户名
-- 此时会话变量为NULLselect @username;
流程控制
内容介绍
在存储过程和自定义函数中可以使用流程控制语句来控制程序的流程。
MySQL 中流程控制语句有:IF 语句、CASE 语句、LOOP 语句、LEAVE 语句、ITERATE 语句、REPEAT 语句和 WHILE 语句等。
判断(IF 语句)
定义
IF 语句用来进行条件判断,根据是否满足条件(可包含多个条件),来执行不同的语句,是流程控制中最常用的判断语句。
语法
IF search_condition THEN statement_list[ELSEIF search_condition THEN statement_list]...[ELSE statement_list]END IF------------------------------------------------------------------------------------------IF 判断条件 THEN 执行语句[ELSELF 判断条件 THEN 执行语句][ELSE 执行语句]END IF
参数介绍
search_condition 参数表示条件判断语句,如果返回值为 TRUE ,相应的 SQL 语句列表(statement_list)被执行;如果返回值为 FALSE,则 ELSE 子句的语句列表被执行。statement_list 可以包括一个或多个语句。
示例
set @username = '张三风';-- 存过创建失败,不清楚原因delimiter $$drop procedure if exists if01$$create procedure if01()beginIF @username = '张三' THENselect concat('我是',@username);ELSEIF @username = '张三风' THENselect '张三是我徒弟';ELSEselect '我是栗四,不认识张三';END IF;end $$delimiter ;call if01;
创建失败原因:最后一个end 后面要跟 “;” 号,可以创建成功,但是执行完依旧报错1064 - ‘$$’ at line 10;但是创建其他存过一样的写法创建正常。
注意事项
MySQL 中的 IF( ) 函数不同于这里的 IF 语句。
判断(CASE 语句)
定义
CASE 语句也是用来进行条件判断的,它提供了多个条件进行选择,可以实现比 IF 语句更复杂的条件判断。
语法
语法一:expr_condition为条件表达式,计算结果为true,则执行THEN后面的语句。多个WHEN…THEN依次执行,ELSE为可选条件。
CASEWHEN expr_condition THEN ...do something...WHEN expr_condition THEN ...do something.......多个 WHEN THEN 语句.....[ELSE ...do something...]END CASE;
语法二:其中,case_value表示条件判断的表达式,WHEN后的表达式结果如果和case_value匹配,则执行相应的THEN后面的语句。没有则执行ELSE,ELSE为可选。(建议使用第一种,逻辑清晰一点)。
CASE case_valueWHEN when_value THEN statement_list[WHEN when_value THEN statement_list]...[ELSE statement_list]END CASE------------------------------------------------------------------CASE 参数变量WHEN 参数变量1 THEN 执行语句][WHEN 参数变量2 THEN 执行语句][ELSE 执行语句]END CASE
参数介绍
case_value 参数表示条件判断的变量,决定了哪一个 WHEN 子句会被执行;
when_value 参数表示变量的取值,如果某个 when_value 表达式与 case_value 变量的值相同,则执行对应的 THEN 关键字后的 statement_list 中的语句;
statement_list 参数表示 when_value 值没有与 case_value 相同值时的执行语句。
CASE 语句都要使用 END CASE 结束。
示例
DELIMITER $$ CREATE PROCEDURE proc1(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 ;
注意事项
方式二类似与 Java 中的 switch…case 语句的使用。 与之区别就是执行时,只要进入其中的一个判断语句之后,就不会在执行其他的,也不需要使用break语句进行跳出。
循环(LOOP 语句)
定义
反复执行循环体中的语句,直到循环结束。如果没有leave等关键字,此时的loop为死循环。
语法
[begin_label:] LOOP statement_list ;END LOOP [begin_label];------------------------------------------------------------------循环名: loop-- 循环体执行语句;end loop 循环名;
示例
-- 需求: 打印1-10,输出结果为 1,2,3,4......9,10-- 如果存在loop_test,则先删除drop procedure if exists loop_test;delimiter $$-- 创建存储过程loop_testcreate procedure loop_test()begindeclare c_index int default 1;declare result_str varchar(256) default '1';cnt: loop-- 循环10次,则跳出循环if c_index >= 10 thenleave cnt;end if;-- 自增set c_index = c_index + 1;-- 拼接select concat(result_str, ',', c_index) into result_str;end loop cnt;-- 查询结果select result_str;end $$delimiter ;call loop_test();
注意事项
loop循环不需要初始条件,这点和while 循环相似,同时和repeat循环一样不需要结束条件。
LEAVE关键字作用
leave 就相当于Java中的break语句,用于跳出当前循环
Java类比代码
public void loop_test() {String result_str = "1";int c_index = 1;while (true) {if (c_index >= 10) {break;}c_index = c_index + 1;result_str = result_str + "," + c_index;}System.out.println(result_str);}
循环(WHILE 语句)
定义
语法
[WHILE标注] : WHILE 条件表达式 DO执行语句END LOOP [WHILE标注];
参数介绍
“WHILE标注” 为可选,表示WHILE循环语句的标签。
示例
drop procedure if exists sp_flow_while;delimiter $$-- 创建存储过程sp_flow_whilecreate procedure sp_flow_while()begindeclare c_index int default 1;-- 收集结果集字符串declare result_str varchar(256) default '1';while c_index < 10 doset c_index = c_index + 1;set result_str = concat(result_str, ',', c_index);end while;-- 查询结果select result_str;end $$delimiter ;call sp_flow_while();
注意事项
WHILE的执行过程是:先判断条件表达式 expr_condition,如果为true执行循环,否则结束循环(与REPEAT的区别是:WHILE先判断条件,REPEAT是后判断条件)。
循环(REPEAT 语句)
定义
repeat在执行操作后检查结果,而while则是执行前进行检查。
语法
[REPEAT标注]:REPEAT执行语句UNTIL 条件表达式END REPEAT [REPEAT标注]
参数介绍
“REPEAT标注” 为可选,表示REPEAT循环语句的标签;
UNTIL指定循环条件。
示例
drop procedure if exists test; -- 如果存在test存储过程则删除delimiter $$ -- 定义标识符为双斜杠create procedure test() -- 创建无参存储过程,名称为testbegindeclare i int default 6; -- 申明变量repeatinsert into test values (i); -- 往test表添加数据set i = i + 1; -- 循环一次,i加一until i > 10 end repeat; -- 结束循环的条件: 当i大于10时跳出repeat循环select * from test; -- 查看test表数据end;$$ -- 结束定义语句delimiter ;
注意事项
REPEAT执行过程是:每次循环体执行完毕需要去判断一下条件表达式expr_condition,如果为true继续执行,否则结束循环。
再次循环(ITERATE 语句)
定义
再次循环,将执行顺序转到语句开头处,只能用于LOOP,REPEAT和WHILE语句内。
语法
ITERATE [LOOP/REPEAT/WHILE标注]
参数介绍
类似于Java代码语言的continue
示例
drop procedure if exists test; -- 如果存在test存储过程则删除delimiter $$ -- 定义标识符为双斜杠create procedure test() -- 创建无参存储过程,名称为testbegindeclare i int(11) default 0; -- 申明变量myloop:loopset i = i + 1;if i < 5 then iterate myloop; -- 跳过本次循环elseif i > 8 then leave myloop;end if;insert into test values (i); end loop myloop;select * from test; end;$$delimiter ; -- 结束定义语句
总结
优点
存储过程可封装,并隐藏复杂的商业逻辑。
存储过程可以回传值,并可以接受参数。
存储过程无法使用 SELECT 指令来运行,因为它是子程序,与查看表,数据表或用户定义函数不同。
存储过程可以用在数据检验,强制实行商业逻辑等。
缺点
存储过程,往往定制化于特定的数据库上,因为支持的编程语言不同。当切换到其他厂商的数据库系统时,需要重写原有的存储过程。
存储过程的性能调校与撰写,受限于各种数据库系统。
参考链接
MySQL(七)存储过程
https://blog.csdn.net/Dim_Jerry/article/details/110203466
mysql存储过程、存储函数(二):流程控制语句
https://blog.csdn.net/weixin_40482816/article/details/112258414
mysql创建定时执行存储过程任务
https://www.cnblogs.com/master-zxc/p/6429266.html
mysql定时任务(event事件)
https://www.cnblogs.com/angryjj/p/11324590.html
MySQL常用操作之创建存储过程语法详解相关推荐
- SQLSERVER存储过程语法详解
SQL SERVER存储过程语法: Create PROC [ EDURE ] procedure_name [ ; number ][ { @parameter data_type }[ VARYI ...
- sql存储过程语法详解
一.定义变量 使用关键字declare申明变量: declare @变量名 变量类型 /*简单赋值*/declare @a intset @a=5print @a/*select赋值*/declare ...
- mysql 创建相同数据库_mysql数据库找出相同数据MySQL常用操作
一.MYSQL的命令行模式的设置:桌面->我的电脑->属性->环境变量->新建-> Path=";pathmysqlbin;"其中path为MySQL ...
- Oracle创建表语句(Create table)语法详解及示例
Oracle创建表语句(Create table)语法详解及示例 创建表(Create table)语法详解 1. ORACLE常用的字段类型ORACLE常用的字段类型有 VARCHAR2 (si ...
- SQL全方位攻略:5. SQL “方言”大比拼:Oracle、MySQL、PostgreSQL限制检索行数语法详解(分页查询)
系列文章目录 SQL全方位攻略:1.数据库介绍 SQL全方位攻略:2.SQL介绍 SQL全方位攻略:3.SQL标准 SQL全方位攻略:4. 标准SQL和SQL"方言" 文章目录 系 ...
- mysql 分库分表 建表,mysql 分库分表 建表MySQL常用操作
通过命令行启动.停止MySQL服务器: start: net start mysql stop: net stop mysql 连接MySQL服务器:\>mysql -h127.0.0.1 -u ...
- MYSQL常用操作 知识梳理
MYSQL常用操作 知识梳理 ==================================增删改查======================================= 创建数据库 ...
- LVM的常用操作【创建lvm】
LVM的常用操作[创建lvm] tips: pv(物理卷).vg(卷组). lv(逻辑卷) 第一步:创建分区并创建pv 虚拟机上挂载一块新的磁盘,使用fdisk工具或者其他硬盘工具给磁盘分区 在分区上 ...
- HBase数据结构与基本语法详解
HBase数据结构与基本语法详解.背景: 阅读新闻 [日期:2019-01-06] 来源:Linux社区 作者:Linux [字体:大 中 小] HBase中的表一般有这样的特点: 1 大:一个表可以 ...
最新文章
- android自定义差值器,如何创建自定义插值器以在android中应用翻译动画
- android studio 打开github开源代码
- 大型网站架构系列:分布式消息队列
- 检测到磁盘可能为uefi引导_【可QQ无偿协助】无法安装windows 因为这台电脑的磁盘布局不受UEFI固件支持...
- php 获取当前目录名称,PHP获取当前执行php文件名的代码
- 【剑指offer】_01 (二维数组中的查找)
- sql server2008r2 没有提示_SQL学习之旅(1)
- 树状数组相关应用之区间更新单点查询问题
- 项目经理的商务指南系列之二:认识责任(敏捷开发,专家与杂家)
- Apache不支持加密的密钥
- nodejs redis 发布订阅_「赵强老师」Redis的消息发布与订阅
- HttpClient 通过资源URL下载资源
- 软件设计师中级考试经验总结
- HttpResponseCode错误码整理
- H3CNE题库(带答案版)
- 如何降低程序员的工资?
- 12、【易混淆概念集】-第六章3 资源平衡 VS 资源平滑 进度压缩 制定进度计划 定义活动 里程碑清单
- IP地址的定义与分类
- 用一年时间如何能掌握 C++ ?
- 计算机第三套演示文稿yswg.pptx,打开考生文件夹下的演示文稿yswg.pptx,根据考生文件夹下的文件“PPT-素材.docx”,按照下列要求完善 - 赏学吧...
热门文章
- Android数据库选哪个,DBFlow—目前最好用的安卓数据库
- 二叉堆的节点插入、删除以及构建过程
- 存款准备金率灾后再度上调
- php mail发送邮件,PHP中利用PHPMailer实现发邮件
- 一,JavaScript基本语法
- H3CTE讲师分享H3C广域网接口和线缆实验
- 正弦波逆变器c语言程序源码,官方开源-EG8010单相纯正弦波逆变器驱动板资料分享...
- RocketMQ原理刨析
- Chrome 浏览器开启黑暗模式
- 电脑无线不显示宽带不能连接服务器,电脑上网为什么只显示宽带连接不显示无线网络连接?...