使用DECLARE定义条件和处理程序
定义条件和处理程序是事先定义程序执行过程中可能遇到的问题,并且可以在处理程序中定义解决这些问题的办法,可以简单理解
为异常处理,这种方式可以提前预测可能出现的问题,并提出解决办法,从而增强程序健壮性。避免程序异常停止,mysql
通过declare关键字定义条件和处理程序。
定义条件
mysql中可以使用declare关键字来定义条件,其基本语法如下:
-- 条件定义语法
declare condition_name condition for condition_value
-- condition_value 的定义格式
sqlstate [value] sqlstate_value | mysql_error_code
其中,condition_name 表示条件的名称,condition_value 参数表示条件的类型;sqlstate_value 参数和mysql_error_code参数都可以
表示 mysql的 错误,如常见的error 1146 (42s02) 中,sqlstate_value 值是42s02,mysql_error_code值是1146,
简单案例如下:
-- 定义主键重复错误
-- error 1062 (23000):duplicate entry '60' for key 'primary'
-- 方法一:使用 sqlstate_value
declare primary_key_duplicate condition for sqlstate '23000';
-- 方法二: 使用mysql_error_code
declare primary_key_duplicate condition for 1062;
定义处理程序
前面定义的处理条件,可以在定义处理程序中 使用,先了解一下定义语法:
declare handler_type HANDLER FOR
condition_value[,...] sp_statement
handler_type 参数的取值有三种:CONTINUE | EXIT | UNDO.
CONTINUE 表示遇到错误不进行处理,继续向下执行;
EXIT 表示遇到错误后马上退出;
UNDO 表示遇到错误后撤回之前的操作,但mysql中暂时还不支持这种处理方式。
我们需要注意的是,大多数情况下,执行过程中遇到错误应该立刻停止执行下面的语句,并且撤回前面的操作。由于mysql目前
并不支持UNDO操作。所以,遇到错误时最好执行EXIT操作。如果事先能够预测错误类型,并且进行相应的处理,那么就选择
CONTINUE 操作。
condition_value 参数指明错误类型,该参数有6个取值。语法如下:
-- condition_value 的取值:
SQLSTATE [VALUE] sqlstate_value
mysql_error_code
condition_name
SQLWARNING
SQLEXCEPTION
sqlstate_value 参数和mysql_error_code参数都可以ysql的错误。如常见的error 1146(42s02)中,sqlstate_value值是42s02,
mysql_error_code值是1146.与条件中参数是一样的。
condition_name 是DECLARE定义的条件名称,就前面定义条件语句
NOT FOUND表示所有以02开头的sqlstate_value值。
SQLEXCEPTION表示所有没有被SQLWARNING或 NOT FOUND捕获的sqlstate_value值。
sp_statement 参数表示要执行存储过程或函数语句。
一下定义了如何捕获和处理异常的简单例子
-- 捕获sqlstate_value值。如果遇到sqlstate_value值为42s02,执行CONTINUE操作,并且设置用户变量info。
DECLARE CONTIUNE HANDLER FOR SQLSTATE '42s02' SET @info='CAN NOT FIND';
-- 捕获mysql_error_code,如果遇到mysql_error_code值为1146,执行CONTIUNE操作,并且设置用户变量info.
DECLARE CONTINUE HANDLER FOR 1146 SET @INFO='CAN NOT FIND';
-- 先定义条件,然后定义处理程序调用
DECLARE can_not_find CONDITION FOR 1146;
-- 定义处理程序,并使用定义的can_not_find 条件
DECLARE CONTINUE HANDLER FOR can_not_find SET @INFO='CAN NOT FIND'
-- SQLWARNING捕获所有以01开头的sqlstate_value值,然后执行EXIT
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='ERROR';
-- NOT FOUND 捕获所有以02开头的sqlstate_value值,然后执行EXIT操作,并且输出"CAN NOT FIND"信息
DECLARE EXIT HANDLER FOR FOUND SET @info='CAN NOT FIND';
-- SQLEXCEPTION 捕获所有没有被SQLWARNING或NOT FOUND 捕获的sqlstate_value 值,然后执行EXIT操作。
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='ERROR';
为了加深理解,下面我们编写一个存储过程用于添加用户,借此来了解定义处理程序的作用,如下:
DELIMITER //
create_procedure sp_insert_user()
begin
set @n=1; -- 设置用户变量,用于标识程序运行到哪一步停止
insert into user value(60,'小米','xiaomi',null,1,null);
set @n=2;
insert into user value(61,'小米2','xiaomi2',null,null);
set @n=3;
end
//
DELIMITER ;
-- 执行存储过程
call sp_insert_user();
-- 报错,因为主键60的用户已存在
ERROR 1062(23000):Duplicate entry '60' for key 'PRIMARY'
-- 查询标识,显然在第一步时遇到错误就停止了执行
select @n;
上述程序在执行完 set @n=1;后就出错了,因为出现了重复的主键值,也就是直接导致后面的程序也无法执行,现在我们编写一个处理程序,使用
存储过程中即使出现2300错误也继续执行,如下:
create procedure insert_user_2()
begin
--定义条件
DECLARE primary_key_exist CONTITION SQLSTATE '23000';
-- 定义处理程序,出现2300错误继续执行, @m用于标识
DECLARE CONTINUE HANDLER FOR primary_key_exist SET @m = 1000;
set @n=1;
insert into user value(60,'小米','小米',null,1,null);
set @n=2;
insert into user value(61,'小米2','xiaomi2',null,1,null);
set @n=3;
end
//
DELIMITER;
call insert_user_2();
-- 查询标识
select @n;
select @m;
从程序可以看出即使出现主键重复错误,但由于我们进行捕获并处理使得整个存储过程的程序可以
执行完成。
构建复杂的存储过程(案例)
获取一个订单的总价,并判断是否需要营业税收,案例如下:
DELIMITER //
create procedure sp_ordertotal(in onnumber int,in taxable boolean,out ototal decimal(8,2))
begin
-- 定义变量:总价
declare total decimal(8,2);
-- 定义默认税收率
declare taxrate int default 6;
-- 关联查询并计算总价
select sum(price * items_num) from orderdetail as od
inner join items as it on it.id=od.items_id
where od.orders_id = onnumber
into total; -- 赋值
-- 判断是否需要营业税收
if taxable then
select total + (total/100 * taxrate) into total;
end if;
-- 赋值给输出参数
select total into ototal;
end
//
-- 执行存储过程
call sp_ordertotal(3,false,@total)//
-- 查询总价
select @total //
存储函数
创建存储函数
上一篇中,我们列举不少mysql自带的函数,但是有些时候自带函数并不能很好满足
我们的需求,此时就需要自定义存储函数了,与存储过程有些类似,简单来说就是
封装一段sql代码,完成一种特定的功能,并返回结果。其语法如下:
create function 函数([参数类型 数据类型[,.....]]) RETURNS 返回类型
begin
sql 语句...
return (返回的数据)
end
与存储过程不通过的是,存储函数中不能指定输出参数(OUT)和输入参数(IN)
类型。存储函数只能指定输入类型而且不能存储函数可以通过return命令将处理
的结果返回给掉用方。注意必须在参数列表后的returns(该值的returns多个s,务必留意)命令中预先指定返回值的类型。
如下创建一个计算斐波那契数列的函数
-- 创建存储函数
create function fn_factorial(num int) returns int
begin
declare result int default 1;
while num > 1 do
set result = result * num;
set num = num -1;
end while;
return result;
end
//
使用 select 执行存储函数
select fn_factorial(5);
这里命名存储函数时使用了【fn_】作为开头,这样可以更容易区分与【sp_】开头的存储过程,从上述语句可以看出前面
在存储过程分析的流程语句也是可以用于存储函数的,同样的, DECLARE声明变量和set设置变量也可用于存储函数,
当然包括定义异常处理语句也是适应的,请注意执行存储函数使用的是select关键字,可同时执行多个存储函数,恩,存储函数就这样
定义,是不是跟存储过程很相似呢,但还是有区别的,这点留到后面分析,下面编写一个用于向user插入用户的存储函数:
-- 创建存储函数fn_insert_user
create function fn_insert_user(name varchar(32),sex char(1)) returns int
begin
insert into user (username,pinyin,birthday,sex,address) values(name,null,null,sex,null);
return LAST_INSERT_ID(); -- 返回最后插入的ID值
end //
DELIMITER ;
-- 执行存储函数
select fn_insert_user('xiaolong',1);
使用DECLARE定义条件和处理程序的更多相关文章
- MySQL 存储过程和存储函数 的定义条件和处理程序
#三.定义条件和处理程序 #mysql 存储函数和过程可以将错误 变成我们想要的处理结果分2步骤 #1.定义错误条件 语法:DECLARE 条件名字 CONDITION for 错误编码 #2. 定义 ...
- Mysql 存储过程(变量、定义条件、处理程序、光标、流程控制构造)
最近由于有同事编写了存储函数,需要进行验证,但是对存储过程一直不是很了解,所以抽时间了解了一下存储过程的基本语法.本篇文章主要包括介绍了存储过程的5个小语法:declare语句的变量.定义条件.处理程 ...
- MYSQL进阶学习笔记四:MySQL存储过程之定义条件,处理过程及存储过程的管理!(视频序号:进阶_11,12)
知识点五:MySQL存储过程之定义条件和处理过程及存储过程的管理(11,12) 定义条件和处理: 条件的定义和处理可以用来定义在处理过程中遇到的问题时相应的处理步骤. DECLARE CONTINUE ...
- C# 中利用 Conditional 定义条件方法
利用 Conditional 属性,程序员可以定义条件方法.Conditional 属性通过测试条件编译符号来确定适用的条件.当运行到一个条件方法调用时,是否执行该调用,要根据出现该调用时是否已定义了 ...
- DECLARE - 定义一个游标
SYNOPSIS DECLARE name [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ] CURSOR [ { WITH | WITHOUT } HOLD ...
- 我的MYSQL学习心得(十) 自定义存储过程和函数
我的MYSQL学习心得(十) 自定义存储过程和函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心 ...
- mysql 存储过程和存储函数
14.1.1 创建存储过程 MySQL中,创建存储过程的基本形式如下: CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristi ...
- mysql数据库存储过程异常处理
14.1.4 定义条件和处理程序 定义条件和处理程序是事先定义程序执行过程中可能遇到的问题.并且可以在处理程序中定义解决这些问题的办法.这种方式可以提前预测可能出现的问题, 并提出解决办法.这样可以 ...
- SqlServer和MySQL游标学习
一 sqlserver游标使用 /*** 游标的使用 讲了这个多游标的优点,现在我们就亲自来揭开游标的神秘的面纱. 使用游标的顺序: 声名游标.打开游标.读取数据.关闭游标.删除游标. 1.3.1 ...
随机推荐
- nginx的四个基本功能
Nginx能做什么 1.反向代理2.负载均衡3.HTTP服务器(包含动静分离)4.正向代理 以上就是做网站小编了解到的Nginx在不依赖第三方模块能处理的事情,下面详细说明每种功能怎么做 1.反向代理 ...
- 项目中的那些事---下载pdf文件
最近做了一个下载pdf文档的需求,本以为使用HTML5中<a>标签的属性download就能简单搞定,不料IE竟然不支持这一简单粗暴的H5新特性,而是直接在网页中打开, 于是各种搜索之后得 ...
- “本地视频使用flashFXP上传虚拟服务器“的方法
一.视频转换格式 首先,想要在网页中直接嵌入视频,就得用video标签,而<video>支持的仅有的几种格式中,MP4是兼容性,通用性各方面相对友好的,所以,建议上传之前先转换格式并压缩. ...
- linux追加中文字库,解决imagemagick 中文乱码的问题。
Windows下的字体丰富多样,而且显示的工整.漂亮. 所以自己想把windows上的字体移到Ubuntu下来.Windows下字体库的位置为C:\Windows\fonts,这里面包含所有windo ...
- Vue--通过button跳转到其他组件并携带id参数
一.创建vue文件 ’ <template> <div> goodsCommon<br/> goodsCommon<br/> goodsCommon&l ...
- Android 程序员不得不收藏的个人博客(持续更新...)
本文已收录我的 Github ,持续更新中 ,欢迎点赞 ! 每周打开一次收藏夹里的个人博客,已经成为了我的人生一大乐趣. 相比各大博客平台,我一直更加偏爱个人博客.在每个人自己的这一亩三分地里,你能看 ...
- ajax成功请求到后台,但是前端报404错误
记录下今天遇见的一个问题,一个删除的ajax请求,传递一个主键到后台,后台成功接受并执行删除,但是前端报POST404错误. 查找原因是由于Controller忘记写返回状态码 @Responsebo ...
- [Vue CLI 3] Uglify 相关的应用和设计
在本文开始之前,先留一个问题? 如果在新版本我想加一个 drop_console 的配置呢? 在老版本的脚手架生成的配置中,对于线上环境的文件:webpack.prod.conf.js 使用了插件:u ...
- 抽象类 abstract class 接口
一.抽象类 1.没有具体的实例. 不可实例化,不能创建对象. 2.抽象类有构造器. 二.abstract 方法. 1.没有方法体. 子类必须重写抽象类的所有抽象方法,才能实例化,否则子类也为抽象类. ...
- java 操作CLOB类型数据
clob类型,但对于这个类型处理起来还是比较麻烦的,varchar2长度为4000bytes,如果varchar2能满足楼主的需求,建议使用varchar2,下面提供了在Java 中读取clob类型的 ...