二十四、MySQL基础系列笔记之异常处理

作者: 温新

分类: 【MySql】

阅读: 2440

时间: 2020-11-18 16:31:47

什么是异常

所写的程序在执行过程中可能会出错,运行时的错误就是异常。

在MySQL中,当存储过程运行出错时,存储过程终止执行并抛出错误信息。

什么情况下需要异常处理

  • 插入数据违反唯一约束;
  • 插入或更新的数据超过字段最大长度;
  • 更新数据与期望的结果不一致。如更新1条数据,却显示更新了5条。

定义异常处理条件

定义异常条件语法

DECLARE 条件名称 CONDITION FOR [条件类型]

条件名称:自定义的名称,建议见名知意

条件类型:mysql_error_code | SQLSTATE sqlstate_value

mysql_error_code和sqlstate_value,sqlstate_value是长度为5的字符串类型错误代码,mysql_error_code为数值类型错误代码。如ERROR 1142(42000)中,sqlstate_value的值是42000,mysql_error_code的值是1142。

定义异常条件简单案例

# 方式一
DECLATE notAllowed CONDITION FOR SQLSTATE '42000';
# 方式二
DECLARE notAllowed CONDITION FOR 1142;

定义条件处理程序语法

DECLARE 处理类型 HANDLER FOR 条件类型

处理类型:CONTINUEEXIT

​ CONTINUE:表示遇到错误不处理,继续执行;

​ EXIT:表示遇到错误立即退出;

条件类型:其取值为SQLSTATE [VALUE] sqlstate_valuecondition_nameSQLWARNINGNOT FOUNDSQLEXCEPTIONmysql_error_code

  • SQLSTATE[VALUE] sqlstate_value 包含5个字符串的字符串错误值;

  • condition_name表示DECLARE CONDITION定义的错误条件名称;

  • SQLWARNING匹配所有以01开头的SQLSTATE错误代码;

  • NOT FOUND 匹配所有以02开头的SQLSTATE错误代码。主要用于游标或select into 变量名

  • SQLEXCEPTION匹配所有没有被SQLWARNING捕获的SQLSTAT错误代码;

  • mysql_error_code匹配数值类型错误代码

定义异常处理程序案例方式

# 方式一 捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info='noSuchTable';
# 方式二 捕获mysql_error_code
DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'noSuchTable';
# 方式三 先定义条件
DECLARE noSuchTable CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR noSuchTable SET @info='noSuchTable';
# 方式四 SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info='error';
# 方式五 NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info='not found';
# 方式六 SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info='sqlexception';

异常处理案例

创建表

CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(60) COLLATE utf8_unicode_ci,
  `email` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `name_and_email` (`name`(20),`email`(20))
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

案例一、使用存储过程创建2张相同的表

错误案例

DROP PROCEDURE IF EXISTS demo03//
create procedure demo03()
begin
	create table t1(id int);
	create table t1(id int);
	select 'ziruchu';
end//
mysql> call demo03()//
ERROR 1050 (42S01): Table 't1' already exists

调用存储过程,由于报错导致 t1表后面的select语句没有执行,若要后面的select语句执行,就需需要忽略报错的地方,然后顺利执行select语句,这就使用到了mysql异常处理。

正确案例

# 方式一、定义条件结合条件异常处理
delimiter //
DROP PROCEDURE IF EXISTS demo03//
create procedure demo03()
begin
	# 定义条件
	declare existed condition for 1050;
	# 条件异常处理,并定义一个变量
	declare continue handler for existed set @fail = 1;
	
	create table t1(id int);
	create table t1(id int);
	select 'ziruchu';
end//

# 调用存储过程
# 可以看到,错误被忽略,ziruchu被输出
call demo03()//


# 方式二、直接使用条件处理程序
DROP PROCEDURE IF EXISTS demo03//
create procedure demo03()
begin
	declare exit handler for sqlstate '42S01' select '42S01异常';
	create table t1(id int);
	create table t1(id int);
	select 'ziruchu';
end//

call demo03()//

方式一:使用continue关键字,即遇到错误并跳过它,执行后面的程序,因此就可以看到 ziruchu 被输出了。

方式二:使用exit关键字,即遇到错误立即停止后面的程序执行,且遇到错误后执行条件异常处理程序后的一个语句,并终止后面的程序执行,因此方式二输出了 '42S01异常'

测试

mysql> call demo0()//
ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'


delimiter //
DROP PROCEDURE IF EXISTS demo04//
create procedure demo04()
begin
	declare continue handler for SQLSTATE '23000' set @a=1;
	insert into t1 values (1);
	insert into t1 values (1);
end//


delimiter //
DROP PROCEDURE IF EXISTS demo04//
create procedure demo04()
begin
	declare continue handler for 1062 set @a=1;
	insert into t1 values (1);
	insert into t1 values (1);
	select 'ziruchu';
end//

注意:SQLSTATE后的错误码必须是字符串,因此必须加引号;for后直接跟mysql_error_code,错误码必须是数值。

2020-11-19

请登录后再评论