MySQL数据库,详解异常捕获及处理(一)
需求背景
我们在写存储过程的时候,可能会出现下列⼀些情况:
1. 插⼊的数据违反唯⼀约束,导致插⼊失败
2. 插⼊或者更新数据超过字段最⼤长度,导致操作失败3. update影响⾏数和期望结果不⼀致遇到上⾯各种异常情况的时,可能需要我们能够捕获,然后可能需要回滚当前事务。
本⽂主要围绕异常处理这块做详细的介绍。
此时我们需要使⽤游标,通过游标的⽅式来遍历select查询的结果集,然后对每⾏数据进⾏处理。
准备数据
创建库:javacode2018
创建表:test1,test1表中的a字段为主键。
/*建库javacode2018*/
drop database if exists javacode2018;
create database javacode2018;
/*切换到javacode2018库*/
use javacode2018;
DROP TABLE IF EXISTS test1;
CREATE TABLE test1(a int PRIMARY KEY);异常分类
我们将异常分为mysql内部异常和外部异常
mysql内部异常
当我们执⾏⼀些sql的时候,可能违反了mysql的⼀些约束,导致mysql内部报错,如插⼊
数据违反唯⼀约束,更新数据超时等,此时异常是由mysql内部抛出的,我们将这些由
mysql抛出的异常统称为内部异常。
外部异常
当我们执⾏⼀个update的时候,可能我们期望影响1⾏,但是实际上影响的不是1⾏数
据,这种情况:sql的执⾏结果和期望的结果不⼀致,这种情况也我们也把他作为外部异
常处理,我们将sql执⾏结果和期望结果不⼀致的情况统称为外部异常。
Mysql内部异常
示例1
test1表中的a字段为主键,我们向test1表同时插⼊2条数据,并且放在⼀个事务
中执⾏,最终要么都插⼊成功,要么都失败。
创建存储过程:
/*删除存储过程*/
DROP PROCEDURE IF EXISTS proc1;
/*声明结束符为$*/
DELIMITER $
/*创建存储过程*/
CREATE PROCEDURE proc1(a1 int,a2 int)
BEGIN
START TRANSACTION;
INSERT INTO test1(a) VALUES (a1);
INSERT INTO test1(a) VALUES (a2);
COMMIT;
END $/*结束符置为;*/
DELIMITER ;
上⾯存储过程插⼊了两条数据,a的值都是1。
验证结果:
mysql> DELETE FROM test1;
Query OK, 0 rows affected (0.00 sec)
mysql> CALL proc1(1,1);
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'
mysql> SELECT * from test1;
+---+
| a |
+---+
| 1 |
+---+
1 row in set (0.00 sec)
上⾯先删除了test1表中的数据,然后调⽤存储过程proc1,由于test1表中的a字
段是主键,插⼊第⼆条数据时违反了a字段的主键约束,mysql内部抛出了异
常,导致第⼆条数据插⼊失败,最终只有第⼀条数据插⼊成功了。
上⾯的结果和我们期望的不⼀致,我们希望要么都插⼊成功,要么失败。
那我们怎么做呢?我们需要捕获上⾯的主键约束异常,然后发现有异常的时候执⾏
rollback回滚操作,改进上⾯的代码,看下⾯⽰例2。
示例2
我们对上⾯⽰例进⾏改进,捕获上⾯主键约束异常,然后进⾏回滚处理,如下:
创建存储过程:
/*删除存储过程*/
DROP PROCEDURE IF EXISTS proc2;
/*声明结束符为$*/
DELIMITER $
/*创建存储过程*/
CREATE PROCEDURE proc2(a1 int,a2 int)
BEGIN /*声明⼀个变量,标识是否有sql异常*/
DECLARE hasSqlError int DEFAULT FALSE;
/*在执⾏过程中出任何异常设置hasSqlError为TRUE*/
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET hasSqlError=TRUE;
/*开启事务*/
START TRANSACTION;
INSERT INTO test1(a) VALUES (a1);
INSERT INTO test1(a) VALUES (a2);
/*根据hasSqlError判断是否有异常,做回滚和提交操作*/
IF hasSqlError THEN
ROLLBACK;
ELSE
COMMIT;
END IF;
END $
/*结束符置为;*/
DELIMITER ;
上⾯重点是这句:
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET hasSqlError=TRUE;
当有sql异常的时候,会将变量hasSqlError的值置为TRUE。
模拟异常情况:
mysql> DELETE FROM test1;
Query OK, 2 rows affected (0.00 sec)
mysql> CALL proc2(1,1);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * from test1;
Empty set (0.00 sec)
上⾯插⼊了2条⼀样的数据,插⼊失败,可以看到上⾯test1表⽆数据,和期望
结果⼀致,插⼊被回滚了。模拟正常情况:
mysql> DELETE FROM test1;
Query OK, 0 rows affected (0.00 sec)
mysql> CALL proc2(1,2);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * from test1;
+---+
| a |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0.00 sec)
上⾯插⼊了2条不同的数据,最终插⼊成功。
相关文章
- 从本体论开始说起——运营商关系图谱的构建及应用
- 如何成为一名数据科学家?
- 从未见过的堂兄杀了人,你的DNA是关键证据
- 20个安全可靠的免费数据源,各领域数据任你挑
- 20个安全可靠的免费数据源,各领域数据任你挑
- 阿里云李飞飞:All in Cloud时代,云原生数据库优势明显
- 基于Hadoop生态系统的一高性能数据存储格式CarbonData(性能篇)
- 大数据告诉你:10年漫威,到底有多少角色
- TigerGraph:实时图数据库助力金融风控升级
- Splunk利用Splunk Connected Experiences和Splunk Business Flow 扩大数据访问
- 大数据开发常见的9种数据分析手段
- 以免在景区看人,我爬了5W条全国景点门票数据...
- 【实战解析】基于HBase的大数据存储在京东的应用场景
- 数据科学家告诉你哪些计算机科学书籍是你应该看的
- Kafka作为大数据的核心技术,你了解多少?
- Spring Boot 整合 Redis 实现缓存操作
- 大数据学习必须掌握的五大核心技术有哪些?
- 基于Antlr在Apache Flink中实现监控规则DSL化的探索实践
- 甲骨文再次被Gartner评为分析型数据管理解决方案魔力象限领导者
- 爬取吴亦凡微博102118条转发数据,扒一扒流量的真假