MySQL存储过程的概念与用法实例

目录
  • 概念
  • 特性
  • 存储过程通常有以下优点
  • 格式
    • 创建存储过程
  • 定义变量
    • 局部变量
    • 用户变量
    • 系统变量
  • 存储过程
    • 存储过程传参-in
    • 存储过程传参-out
    • 存储过程传参-inout
  • 流程控制
    • 流程控制-判断
    • 流程控制语句-case
    • 控制流程-循环
      • while循环
      • repeat循环
      • loop循环
  • 游标
  • 异常处理-HANDLER句柄
  • 总结

概念

MySQL5.0版本开始支持存储过程,存储过程就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法,存储过就是数据库SQL与层层面的代码封装与重用

特性

1.有输入输出参数,可以声明变量,有if/else/case/while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能

2.函数的普通特性:模块化,封装,代码复用

3.速度快,只有首次执行需要经过编译和优化步骤,后续被调用可以直接执行,省去以上步骤

存储过程通常有以下优点

(1).存储过程增强了SQL语言的功能和灵活性。存储过程可以用流控制语句编写,有很强的灵活性,可以完成复杂的判断和较复杂的运算。

(2).存储过程允许标准组件是编程。存储过程被创建后,可以在程序中被多次调用,而不必重新编写该存储过程的SQL语句。而且数据库专业人员可以随时对存储过程进行修改,对应用程序源代码毫无影响。

(3).存储过程能实现较快的执行速度。如果某一操作包含大量的Transaction-SQL代码或分别被多次执行,那么存储过程要比批处理的执行速度快很多。因为存储过程是预编译的。在首次运行一个存储过程时查询,优化器对其进行分析优化,并且给出最终被存储在系统表中的执行计划。而批处理的Transaction-SQL语句在每次运行时都要进行编译和优化,速度相对要慢一些。

(4).存储过程能过减少网络流量。针对同一个数据库对象的操作(如查询、修改),如果这一操作所涉及的Transaction-SQL语句被组织程存储过程,那么当在客户计算机上调用该存储过程时,网络中传送的只是该调用语句,从而大大增加了网络流量并降低了网络负载。

(5).存储过程可被作为一种安全机制来充分利用。系统管理员通过执行某一存储过程的权限进行限制,能够实现对相应的数据的访问权限的限制,避免了非授权用户对数据的访问,保证了数据的安全。

格式

创建存储过程

-- 创建存储过程
delimiter $$
create procedure proc01()
begin
	select empno,ename from emp;
end $$
delimiter ;
-- 调用存储过程
call proc01;

定义变量

局部变量

用户自定义,在begin/end块中有效

delimiter $$
create procedure proc02()
begin
	declare var_name01 varchar(20) default 'aaa';  -- 声明/定义变量
	set var_naem01 = 'zhangsan'; -- 给变量赋值
	select var_name01; -- 输出变量的值
end $$
dilimiter ;
call proc02();

用户变量

用户自定义,当前会话(连接)有效.类比java的成员变量

delimiter $$
create procedure proc04()
begin
	set @var_name01 = 'beijing';
	select @var_name01;
end $$
dilimiter ;
call proc04();
select @var_name01; -- 外部也是可以使用用户变量

系统变量

1.系统变量有分为全局变量会话变量

2.全局变量在MYSQL启动的时候由服务器自动将他的初始化为默认值,这些默认值可以通过更改my.ini这个文件来更改

3.会话变量在每次建立一个新的连接的时候,由MYSQL来初始化,MYSQL会将当前所有全局变量的值复制一份,来作为会话变量

4.也就是说,如果在建立会话以后,没有手动更改过会话变量与全局变量的值,那所有这些变量的值都是一样的

5.全局变量与会话变量的区别在于,对全局变量的修改会影响整个服务器,但是对会话变量的修改,只会影响到当前的会话(也就是当前的数据库连接)

6.有些系统变量的值是可以利用语句来动态进行更改的,但是有些系统变量的值缺是只读的,对于那些可以更改的系统变量,我们可以利用set语句进行更改

系统变量-全局变量

由系统系统,在整个数据库中有效

存储过程

存储过程传参-in

in表示传入的参数,可以传入数值或者变量,即使传入变量,并不会改变变量的值,可以内部更改,仅仅作用在函数范围内

delimiter $$
create procedure proc06(in param_empno int)
begin
	select*from emp where empno = param_empno
end $$
delimiter ;
call proc06(1001);

多个参数传参

存储过程传参-out

out表示从存储过程内部传值给调用者

存储过程传参-inout

inout表示从外部传入的参数经过修改后可以返回的变量,既可以使用传入变量的值也可以修改变量的值(即使函数执行完)

流程控制

流程控制-判断

IF语句包含多个条件判断,根据结果为TURE和FALSE执行语句,与编程语言中的if、else if、else语法类似,其语法格式如下

-- 存储过程-if
-- 案例1
-- 输入学生的成绩,来判断成绩的级别
/*
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)
begin
	if score<60 then select '不及格';
	elseif score>=60 and score<80 then select '及格';
	elseif score>=80 and score<90 then select '良好';
	elseif score>=90 and score<=100 then select '优秀';
	else select '成绩错误'
	end if;
end $$
delimiter ;

set @score=55;
call proc_12_if(@score)
-- 输入员工的名字,判断工资的情况
/*
sal<10000 :适用薪资
sal>=10000 and sal<20000 :转正薪资
sal>=20000 :元老薪资
*/
delimiter $$
create procedure proc_13_if(in in_ename varchar)
begin
	declare var_sal decimal(7,2);  -- 定义局部变量,7个长度,2个小数
	declare result varchar(20);
	select sal into var_sal from emp where ename=in_eanme;  -- 将值赋给局部变量
	if var_sal <10000 then set result ='适用薪资';
	elseif var_sal <20000 then set result ='转正薪资';
	else set result ='元老薪资';
	end if;
	select result;
end$$
delimiter ;

-- 调用
call proc_13_if('刘备');

流程控制语句-case

CASE是另一个条件判断语句,类似于编程语言中的switch语法

语法一:当case后面的语句与when后面的语句相等时,则会执行then后面的语句,如果均不匹配则执行else

语法二:直接写case 当when后面的条件成立则执行then后面的语句,如果都不成立,则执行else

-- 流程控制语句:case
/*
支付方式:
	1.微信支付
	2.支付宝支付
	3.银行卡支付
	4.其他支付
*/
-- 格式1
delimiter $$
create procedure proc14_case(in pay_type int)
begin
	case pay_type
	when 1 then select '微信支付';
	when 2 then select '支付宝支付';
	when 3 then select '银行卡支付';
	else select '其他方式支付';
	end case;
end$$
delimiter ;

call proc14_case(2);
call proc14_case(3);
-- 语法二
-- 输入学生的成绩,来判断成绩的级别
/*
score<60:不及格
score>=60 , score<80 :及格
score>=80 , score<90 :良好
score>=90 , score<=100 :优秀
score>100 :成就错误
*/
delimiter $$
create procedure proc_15_case (in score int)
begin
	case
	when score<60 then select '不及格';
	when score>=60 and score<80 then select '及格';
	when score>=80 and score<90 then select '良好';
	when score>=90 and score<=100 then select '优秀';
	else select '成绩错误'
	end case;
end $$
delimiter ;

call proc_15_case(88);

控制流程-循环

概述

循环是一段在程序中只出现一次,但可能会连续运行多次的代码

循环中的代码会运行特定的次数,或者是运行到特定条件成立时结束循环

循环分类

while、repeat、loop

循环控制

leave 类似于break,跳出,结束当前所在的循环

iteater 类似于continue,继续,结束本次循环,继续下一次

while循环

-- 需求:向表中添加指定条数据
-- while
delimiter $$
create procedure proc16_while(in insertCount int)
begin
	declare i int default 1;  -- 设置循环的增量
	label:while i<=insertCount do insert into user(id,username,password) values(i,concat('user-',i),'123456');
	set i=i+1;
end while label;
end$$
delimiter ;

call proc16_while(10);
-- 需求:向表中添加指定条数据
-- while+leave
delimiter $$
create procedure proc16_while(in insertCount int)
begin
	declare i int default 1;  -- 设置循环的增量
	label:while i<=insertCount do insert into user(id,username,password) values(i,concat('user-',i),'123456');
	if i=5 then leave label;   -- 如果i=5则跳出循环
	set i=i+1;
end while label;
end$$
delimiter ;

call proc16_while(10);

repeat循环

格式

-- 存储过程-循环控制-repeat

delimiter $$
create procedure proc18_repaet(in insertCount int)
begin
	declare i int default 1;
	label:repeat
		insert into user(uid,username,password)values(i,concat('user-',i),'123456');
		set i = i+1;
		until i>inserCount  -- 这里不能写; 表示跳出循环
		end repeat label;
		select '循环结束';
end$$
delimiter ;

call proc18_repeat(100);

loop循环

-- 存储过程-循环控制-loop

delimiter $$
create procedure proc19_loop(in insertCount int)
begin
	declare i default 1;
	label:loop insert into user (uid,username,password) values (i,concat('user-')i,'123456');
	set i= i+1;
	if i>insertCount then leave label;
	end if;
	end loop label;
end$$
delimiter ;

call proc19_loop()

游标

游标(cursor)是庸才存储查询结果集的数据类型,在存储过程和函数中可以使用光标对结果集进行循环的处理,光标的使用包括光标的声明、OPEN、FETCH、CLOSE

-- 操作游标(cursor)
-- 声明游标
-- 打开游标
-- 通过游标获取值
-- 关闭游标
-- 需求:输入一个部门名,查询该部门员工的编号、名字、薪资,将查询的结果集添加游标
delimiter $$
create procedure proc19_cursor(in in_danme varchar(50))
begin
 -- 定义局部变量
	declare var_empno int;
	declare var_ename varchar(50);
	declare var_sal decimal(7,2);
 -- 声明游标
	declare my_cursor cursor for select empno,ename,sal from dept a,emp b where a.deptno=b.deptno and a.dname=in_dname;
 -- 打开游标
	open my_cursor;
 -- 通过游标获取值
-- 	fetch my_cursor into var_empno,var_ename,var_sal;
-- 	select var_empno,var_ename,var_sal;  -- 注意:以上两句只可以获取一个数据,因为游标是一次一行,所以采用循环
	label:loop
		fetch my_cursor into var_empno,var_ename,var_sal;
		select var_empno,var_ename,var_sal;
	end loop label;
 -- 关闭游标
 close my_cursor;
end$$
delimiter ;

call proc19_cursor('销售部');

异常处理-HANDLER句柄

MySQL存储过程也提供了对异常处理的功能:通过定义HANDLER来完成异常声明的实现

格式

在语法中,变量声明、游标声明、handler声明必须按照先后顺序书写的,否则创建存储过程出错

DECALARE handler_action 创建句柄

FOR 后面为条件值,为什么异常提供处理

statment 当没有数据发现这个异常发生时采取什么措施

handler_action :{

CONTINUE    继续执行

EXIT 退出

UNDO 取消(目前MySQL不支持)

}

condition_value :{

mysql_error_code  错误码

condition 条件名

SQLWARNING   SQL警告

NOT FOUND  数据没有发现

SQLEXCEPTION  SQL异常

}

/*用于测试句柄,改造上面游标代码会出现1329错误代码的情况*/
-- 操作游标(cursor)
-- 声明游标
-- 打开游标
-- 通过游标获取值
-- 关闭游标
-- 需求:输入一个部门名,查询该部门员工的编号、名字、薪资,将查询的结果集添加游标
delimiter $$
create procedure proc21_cursor_handler(in in_danme 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 for select empno,ename,sal from dept a,emp b where a.deptno=b.deptno and a.dname=in_dname;
 -- 定义句柄:定义异常的处理方式
 /*
 1:异常处理完之后,程序应该如何执行
		continue :继续执行剩余代码
		exit:直接终止程序
		undo:不支持
 2:触发条件
		条件码:1329.....
		条件名:
					SQLWARNING
					NOT FOUND
					SQLEXCEPTION
 3:异常触发之后执行什么代码
		设置flag的值 -> 0
 */
  declare continue handler for 1329 set flag=0 ;
 -- 打开游标
	open my_cursor;
 -- 通过游标获取值
-- 	fetch my_cursor into var_empno,var_ename,var_sal;
-- 	select var_empno,var_ename,var_sal;  -- 注意:以上两句只可以获取一个数据,因为游标是一次一行,所以采用循环
	label:loop
		fetch my_cursor into var_empno,var_ename,var_sal;
		-- 判断flag的值如果为1则执行,否则不执行
		if flag =1 then
		 select var_empno,var_ename,var_sal;
		else leave label;
		end if;
	end loop label;
 -- 关闭游标
 close my_cursor;
end$$
delimiter ;

call proc19_cursor('销售部');

总结

到此这篇关于MySQL存储过程的概念与用法的文章就介绍到这了,更多相关MySQL存储过程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySql存储过程与函数详解

    存储过程和函数是在数据库中定义一些SQL语句的集合,然后直接调用这些存储过程和函数来执行已经定义好的SQL语句.存储过程和函数可以避免开发人员重复的编写相同的SQL语句.而且,存储过程和函数是在MySQL服务器中存储和执行的,可以减少客户端和服务器端的数据传输. 一.存储过程 1.1.基本语法 CREATE PROCEDURE sp_name ([proc_parameter[,...]])    [characteristic ...] routine_body Sp_name:存储过程的名称

  • MySQL存储过程使用实例详解

    例1.一个简单存储过程游标实例 复制代码 代码如下: DELIMITER $$ DROP PROCEDURE IF EXISTS getUserInfo $$CREATE PROCEDURE getUserInfo(in date_day datetime)-- -- 实例-- 存储过程名为:getUserInfo-- 参数为:date_day日期格式:2008-03-08--    BEGINdeclare _userName varchar(12); -- 用户名declare _chine

  • 深入mysql创建自定义函数与存储过程的详解

    一 创建自定义函数在使用mysql的过程中,mysql自带的函数可能不能完成我们的业务需求,这时就需要自定义函数,例如笔者在开发过程中遇到下面这个问题:mysql表结构如下 复制代码 代码如下: DROP TABLE IF EXISTS `test`;CREATE TABLE `test` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `pic` varchar(50) NOT NULL,  `hashcode` varchar(16) N

  • mysql存储过程详解

    1.存储过程简介 我们常用的操作数据库语言SQL语句在执行的时候需要要先编译,然后执行,而存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中,用户通过指定存储过程的名字并给定参数(如果该存储过程带有参数)来调用执行它. 一个存储过程是一个可编程的函数,它在数据库中创建并保存.它可以有SQL语句和一些特殊的控制结构组成.当希望在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的.数据库中的存储过程可以看做是对编程中面

  • Mysql存储过程和函数区别介绍

    存储过程是用户定义的一系列sql语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表. 存储过程和函数存在以下几个区别: 1)一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强.存储过程,功能强大,可以执行包括修改表等一系列数据库操作:用户定义函数不能用于执行一组修改全局数据库状态的操作. 2)对于存储过程来说可以返回参数,如记录集,而函数只能返回值或者表对象.函数只能返回一个变量:而存

  • MySql存储过程之逻辑判断和条件控制

    具体详情请看下文小编给大家带来的知识点. 同编写程序类似,存储过程中也有对应的条件判断,功能类似于if.switch.在MySql里面对应的是IF和CASE 1.IF判断 IF判断的格式是这样的: IF expression THEN commands [ELSEIF expression THEN commands] [ELSE commands] END IF; 这里expression是我们的判断表达式:ELSE IF 和ELSE都是可选的:command就是当条件为真(true为1,fa

  • mysql存储过程 游标 循环使用介绍

    Mysql的存储过程是从版本5才开始支持的,所以目前一般使用的都可以用到存储过程.今天分享下自己对于Mysql存储过程的认识与了解. 一些简单的调用以及语法规则这里就不在赘述,网上有许多例子.这里主要说说大家常用的游标加循环的嵌套使用. 首先先介绍循环的分类: (1)WHILE ... END WHILE (2)LOOP ... END LOOP (3)REPEAT ... END REPEAT (4)GOTO 这里有三种标准的循环方式:WHILE循环,LOOP循环以及REPEAT循环.还有一种

  • MYSQL的存储过程和函数简单写法

    什么是存储过程 简单的说,就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法: ps:存储过程跟触发器有点类似,都是一组SQL集,但是存储过程是主动调用的,且功能比触发器更加强大,触发器是某件事触发后自动调用: 有哪些特性 有输入输出参数,可以声明变量,有if/else, case,while等控制语句,通过编写存储过程,可以实现复杂的逻辑功能: 函数的普遍特性:模块化,封装,代码复用: 速度快,只有首次执行需经过编译和优化步骤,后续被调用可以直接执行,省

  • MySQL存储过程的概念与用法实例

    目录 概念 特性 存储过程通常有以下优点 格式 创建存储过程 定义变量 局部变量 用户变量 系统变量 存储过程 存储过程传参-in 存储过程传参-out 存储过程传参-inout 流程控制 流程控制-判断 流程控制语句-case 控制流程-循环 while循环 repeat循环 loop循环 游标 异常处理-HANDLER句柄 总结 概念 MySQL5.0版本开始支持存储过程,存储过程就是一组SQL语句集,功能强大,可以实现一些比较复杂的逻辑功能,类似于JAVA语言中的方法,存储过就是数据库SQ

  • mysql索引基数概念与用法示例

    本文实例讲述了mysql索引基数概念与用法.分享给大家供大家参考,具体如下: Cardinality(索引基数)是mysql索引很重要的一个概念 索引基数是数据列所包含的不同值的数量.例如,某个数据列包含值1.2.3.4.5.1,那么它的基数就是5.索引的基数相对于数据表行数较高(也就是说,列中包含很多不同的值,重复的值很少)的时候,它的工作效果最好.如果某数据列含有很多不同的年龄,索引会很快地分辨数据行.如果某个数据列用于记录性别(只有"M"和"F"两种值),那么

  • MySQL数据类型中DECIMAL的用法实例详解

    MySQL数据类型中DECIMAL的用法实例详解 在MySQL数据类型中,例如INT,FLOAT,DOUBLE,CHAR,DECIMAL等,它们都有各自的作用,下面我们就主要来介绍一下MySQL数据类型中的DECIMAL类型的作用和用法. 一般赋予浮点列的值被四舍五入到这个列所指定的十进制数.如果在一个FLOAT(8, 1)的列中存储1. 2 3 4 5 6,则结果为1. 2.如果将相同的值存入FLOAT(8, 4) 的列中,则结果为1. 2 3 4 6. 这表示应该定义具有足够位数的浮点列以便

  • Mysql inner join on的用法实例(必看)

    语法规则 SELECT column_name(s) FROM table_name1 INNER JOIN table_name2 ON table_name1.column_name=table_name2.column_name 先创建两个表,1.用户,2.用户类别 用户表 CREATE TABLE `user` ( `id` int(32) NOT NULL AUTO_INCREMENT, `name` varchar(16) NOT NULL, `kindid` int(32) NOT

  • MySQL中Like概念及用法讲解

    Like中文解释为喜欢的意思,但当应用于MySQL数据库中,Like则是一种语句,用于模糊查询,主要是针对字符型字段的,在一个字符型字段列中检索包含对应子串的.本文向大家介绍MySQL中Like语句. 一.Like是什么意思 1.Like算作MySQL中的谓词,其应用与is.=.>和<等符号用法类似. 2.在sql结构化查询语言中,like语句有着至关重要的作用. 3.从某种意义上讲,Like可看作是一个精简的正则表达式功能. 二.Like作用 like语句的语法格式是 select * fr

  • MySQL联合索引功能与用法实例分析

    本文实例讲述了MySQL联合索引功能与用法.分享给大家供大家参考,具体如下: 联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效. 两个或更多个列上的索引被称作复合索引. 利用索引中的附加列,您可以缩小搜索的范围,但使用一个具有两列的索引 不同于使用

  • PHP流Streams、包装器wrapper概念与用法实例详解

    本文实例讲述了PHP流Streams.包装器wrapper概念与用法.分享给大家供大家参考,具体如下: 流Streams这个概念是在php4.3引进的,是对流式数据的抽象,用于统一数据操作,比如文件数据.网络数据.压缩数据等,以使可以共享同一套函数,php的文件系统函数就是这样的共享,比如file_get_contents()函数即可打开本地文件也可以访问url就是这一体现.简单点讲,流就是表现出流式数据行为的资源对象. 以线性方式进行读写,并可以在流里面任意位置进行搜索. 流有点类似数据库抽象

  • MySQL中USING 和 HAVING 用法实例简析

    本文实例讲述了MySQL中USING 和 HAVING 用法.分享给大家供大家参考,具体如下: USING 用于表连接时给定连接条件(可以理解为简写形式),如 SELECT * FROM table1 JOIN table2 ON table1.id = table2.id 使用 USING 可以写为 SELECT * FROM table1 JOIN table2 USING(id) HAVING 引入 HAVING 是因为 WHERE 无法和统计函数一起使用 如表 order (定单)有如下

  • mysql共享锁与排他锁用法实例分析

    本文实例讲述了mysql共享锁与排他锁用法.分享给大家供大家参考,具体如下: mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改. 排他锁又称为写锁,简称X锁,顾名思义,排他锁就是不能与其他所并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据

  • mysql累积聚合原理与用法实例分析

    本文实例讲述了mysql累积聚合原理与用法.分享给大家供大家参考,具体如下: 累积聚合为聚合从序列内第一个元素到当前元素的数据,如为每个员工返回每月开始到现在累积的订单数量和平均订单数量 行号问题有两个解决方案,分别是为使用子查询和使用连接.子查询的方法通常比较直观,可读性强.但是在要求进行聚合时,子查询需要为每个聚合扫描一次数据,而连接方法通常只需要扫描一次就可以得到结果.下面的查询使用连接来得到结果 SELECT a.empid, a.ordermonth,a.qty AS thismont

随机推荐