declare handler 声明异常处理的语法

声明异常处理的语法

DECLARE
{EXIT | CONTINUE}
HANDLER FOR
{error-number | SQLSTATE error-string | condition}
SQL statement

上述定义包括:

Handler Type (CONTINUE,EXIT)//处理类型 继续或退出

Handler condition (SQLSTATE,MYSQL ERROR,CONDITION)//触发条件

Handler actions(错误触发的操作)

注意:

1、exit只退出当前的block。exit 意思是当动作成功提交后,退出所在的复合语句。即declare exit handler for... 所在的复合语句。

2、如果定义了handler action,会在continue或exit之前执行

发生错误的条件有:

1、MYSQL错误代码

2、ANSI-standard SQLSTATE code

3、命名条件。可使用系统内置的SQLEXCEPTION,SQLWARNING和NOT FOUND

例1:

当错误代码为1062时将duplicate_key的值设为1,并继续执行当前任务

declare continue handler for 1062 set duplicate_key=1;

下面的跟上面一样,只是使用的条件为ANSI标准错误代码

declare continue handler for sqlstate '23000' set duplicate_key=1;

当发生SQLEXCEPTION时,将L_error设为1,并继续

declare continue handler for SQLEXCEPTION set L_error=1;

小提示:

当你在MYSQL客户端执行命令并产生错误时,会得到MYSQL和ANSI的SQLSTATE code,如:

附常见错误号对照表

MySQL error code SQLSTATE code Error message

1011 HY000 Error on delete of '%s' (errno: %d)
1021 HY000 Disk full (%s); waiting for someone to free some space . . .
1022 23000 Can't write; duplicate key in table '%s'
1027 HY000 '%s' is locked against change
1036 HY000 Table '%s' is read only
1048 23000 Column '%s' cannot be null
1062 23000 Duplicate entry '%s' for key %d
1099 HY000 Table '%s' was locked with a READ lock and can't be updated
1100 HY000 Table '%s' was not locked with LOCK TABLES
1104 42000 The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET SQL_MAX_JOIN_SIZE=# if the SELECT is okay
1106 42000 Incorrect parameters to procedure '%s'
1114 HY000 The table '%s' is full
1150 HY000 Delayed insert thread couldn't get requested lock for table %s
1165 HY000 INSERT DELAYED can't be used with table '%s' because it is locked with LOCK TABLES
1242 21000 Subquery returns more than 1 row
1263 22004 Column set to default value; NULL supplied to NOT NULL column '%s' at row %ld
1264 22003 Out of range value adjusted for column '%s' at row %ld
1265 1000 Data truncated for column '%s' at row %ld
1312 0A000 SELECT in a stored program must have INTO
1317 70100 Query execution was interrupted
1319 42000 Undefined CONDITION: %s
1325 24000 Cursor is already open
1326 24000 Cursor is not open
1328 HY000 Incorrect number of FETCH variables
1329 2000 No data to FETCH
1336 42000 USE is not allowed in a stored program
1337 42000 Variable or condition declaration after cursor or handler declaration
1338 42000 Cursor declaration after handler declaration
1339 20000 Case not found for CASE statement
1348 HY000 Column '%s' is not updatable
1357 HY000 Can't drop a %s from within another stored routine
1358 HY000 GOTO is not allowed in a stored program handler
1362 HY000 Updating of %s row is not allowed in %s trigger
1363 HY000 There is no %s row in %s trigger

命名条件:

declare conditon_name condition for {SQLSTATE sqlstate_code | MYSQL_ERROR_CODE};

例如:

declare foreign_key_error condition for 1216;

declare continue handler for foreign_key_error mysql_statements;

优先级:当同时使用MYSQL错误码,标准SQLSTATE错误码,命名条件(SQLEXCEPTION)来定义错误处理时,其捕获顺序是(只捕获一条错误):MYSQL码->SQLSTATE->命名条件

作用域:

1、包括begin...end内的语句

declare continue handler for 1048 select 'attempt to insert a null value';
begin
  insert into a values(6,null);
end;

 

若a表第二字段定义为非空,则会触发1048错误

2、若错误处理在begin...end内定义,则在之外的语句不会触发错误发生

BEGIN
  BEGIN
    DECLARE CONTINUE HANDLER FOR 1216 select 'Foreign key constraint violated';
  END;
  INSERT INTO departments (department_name,manager_id,location) VALUES ('Elbonian HR','Catbert','Catbertia');
END;

3、能够捕获其它存储过程抛出的错误

下面再通过几个例子来掌握MySQL存储过程中异常处理的使用。

例一:error-number

准备工作

CREATE TABLE `t1` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
CREATE TABLE `t2` (
  `cid` INT(10) UNSIGNED NULL DEFAULT NULL,
  INDEX `FK__t1` (`cid`),
  CONSTRAINT `FK__t1` FOREIGN KEY (`cid`) REFERENCES `t1` (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

创建存储过程 

delimiter //
create procedure a(var1 int)
begin
  declare exit handler for 1452 insert into error_log values(
    concat('time:',current_date,'.Foreign Key Reference Failure For Value=',var1)
  );
  insert into t2 values(var1);
end;//

如果有1452错误,则当插入到表error_log这个语句完成后,退出(exit),这里申明异常处理的语句在上面begin...end的复合语句中,所以这里退出,其实就表示退出了该存储过程。

例二:sqlstate error-string

准备工作

CREATE TABLE `t4` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

 

create procedure p23()
begin
  begin
  declare exit handler for sqlstate '23000' set @x2=1;
    set @x=1;
    insert into t4 values(1);
    set @x=2;
  end;
  begin
    declare exit handler for sqlstate '23000' set @x2=9;
    insert into t4 values(1);
  end;
  set @x=3;
end

结果:

例三:

begin
  declare exit handler for sqlstate '23000' set @x2=1;
  set @x=1;
  insert into t4 values(1);
  set @x=2;
  begin
    declare exit handler for sqlstate '23000' set @x2=9;
    insert into t4 values(1);
  end;
  set @x=3;
end

结果:

在执行一次该存储过程,得到结果如下:

error-number的例子

create procedure p22(var1 int)
begin
  declare exit handler for 1216 insert into error_log values(
    concat('time:' , current_date , '.Foreign Key Reference Failure For Value='
    ,var1)
  );
  insert into t3 values(var1);
end;//

sqlstate error-string的例子

create procedure p23()
begin
  declare continue handler for sqlstate '23000' set @x2=1;
  set @x=1;
  insert into t4 values(1);
  set @x=2;
  insert into t4 values(1);
  set @x=3;
end;//

执行结果:


condition的例子

declare 'name' condition for sqlstate '23000';
declare exit handler for 'name' rollback;

 

转载于:https://www.cnblogs.com/datoubaba/archive/2012/06/20/2556428.html

<think>好的,我现在需要处理用户的问题:“declare exit handler for”。用户之前询问了关于SQL中的DECLARE语句,现在转向了DECLARE的另一个用法,即声明退出处理器。这可能意味着他们在编写存储过程或触发器时遇到了错误处理的需求。 首先,我要确认用户的基础知识。他们可能已经了解如何声明变量,现在想进一步学习错误处理机制。用户提到的“exit handler”是SQL中的异常处理部分,特别是在MySQL中常见。需要解释清楚DECLARE HANDLER语法和作用,以及exit handler与其他类型(如continue handler)的区别。 接下来,我需要分析用户可能的实际应用场景。例如,他们可能在存储过程中需要捕获错误,记录日志,或者执行回滚操作。用户可能希望确保在发生错误时,程序能够优雅地处理,而不是直接终止。因此,实际示例会很有帮助,比如在事务中使用exit handler来回滚,并设置变量记录错误信息。 同时,用户可能对语法结构不太清楚,需要详细说明每个部分的作用,比如FOR后面的条件(SQLEXCEPTION, SQLWARNING等),以及语句执行后的行为(exit还是continue)。还要注意不同数据库系统之间的差异,比如MySQL和PostgreSQL在错误处理上的不同实现,但用户之前的问题提到的是SQLCODE和SQLERRM,这通常在MySQL中使用,所以应重点讲解MySQL的用法。 另外,用户可能关心如何在实际代码中使用这些处理器,例如如何获取错误代码和消息,并将其存储在变量中。需要举例说明DECLARE EXIT HANDLER与变量赋值的结合使用,以及处理后的流程控制,比如在发生错误时退出当前块并执行清理操作。 最后,应该提醒用户注意事项,比如处理器的声明顺序,作用域的问题,以及过度使用exit handler可能带来的性能影响。同时,回答需要结构清晰,分点说明,确保用户能够逐步理解概念和应用方法。</think>### `DECLARE EXIT HANDLER FOR` 详解 `DECLARE EXIT HANDLER FOR` 是 SQL 存储过程或函数中用于 **定义错误处理逻辑** 的语句。它允许在程序执行过程中捕获特定类型的错误(如异常、警告等),并在触发错误时执行预先定义的操作(如回滚事务、记录日志或修改变量)。 --- #### 一、基本语法 ```sql DECLARE [ACTION] HANDLER FOR [CONDITION] [STATEMENT]; ``` - **`ACTION`**:定义触发后的行为,常见两种类型: - `EXIT`:执行完处理逻辑后,**立即退出当前 BEGIN...END 块**。 - `CONTINUE`:执行完处理逻辑后,**继续执行后续代码**。 - **`CONDITION`**:指定要捕获的错误类型,例如: - `SQLEXCEPTION`:所有异常(如主键冲突、数据类型不匹配)。 - `SQLWARNING`:警告(如数据截断)。 - `NOT FOUND`:查询无结果的场景(如 `SELECT ... INTO` 未找到数据)。 - 自定义错误代码(如 `SQLSTATE '42S02'` 表示表不存在)。 - **`STATEMENT`**:触发错误后要执行的 SQL 语句(可以是单条语句或 `BEGIN...END` 代码块)。 --- #### 二、核心作用 1. **错误捕获与处理** 在存储过程执行时,如果发生错误(如违反约束、死锁等),可以自动触发预定义的逻辑(例如回滚事务或记录错误信息),避免程序直接崩溃。 2. **控制执行流程** 通过 `EXIT` 或 `CONTINUE` 决定是否终止当前代码块的执行。 3. **增强健壮性** 确保关键操作(如事务)在失败时有明确的恢复机制,避免脏数据或资源泄漏。 --- #### 三、典型示例 以下示例演示如何在事务中捕获错误并回滚: ```sql CREATE PROCEDURE safe_transfer() BEGIN -- 定义变量和错误标志 DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; -- 发生异常时回滚事务 SET @error = 1; -- 设置错误标志 END; START TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE user_id = 1; UPDATE accounts SET balance = balance + 100 WHERE user_id = 2; COMMIT; SET @error = 0; -- 标记成功 END; ``` - 若任意一条 `UPDATE` 失败(如余额不足或账户不存在),会触发 `EXIT HANDLER`,回滚事务并设置 `@error = 1`。 - 若全部成功,则提交事务并设置 `@error = 0`。 --- #### 四、高级用法 1. **捕获特定错误** 捕获表不存在的错误(`SQLSTATE '42S02'`): ```sql DECLARE EXIT HANDLER FOR SQLSTATE '42S02' BEGIN SELECT '表不存在,请检查!' AS error_msg; END; ``` 2. **同时捕获多种错误** 捕获所有异常和警告: ```sql DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING BEGIN -- 记录日志或清理操作 END; ``` 3. **与 `GET DIAGNOSTICS` 结合** 获取详细错误信息(如错误代码和消息): ```sql DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN GET DIAGNOSTICS CONDITION 1 @sqlcode = RETURNED_SQLSTATE, @errmsg = MESSAGE_TEXT; INSERT INTO error_log VALUES (@sqlcode, @errmsg, NOW()); END; ``` --- #### 五、注意事项 1. **声明顺序** `DECLARE HANDLER` 必须位于所有其他语句之前(紧随 `BEGIN` 之后)。 2. **作用域限制** 处理器仅在当前 `BEGIN...END` 块内有效,嵌套块可定义独立的处理器。 3. **性能影响** 过度使用可能增加代码复杂度,但合理设计可显著提升程序可靠性。 --- #### 六、与其他数据库的差异 - **MySQL**:支持 `DECLARE HANDLER`,语法与上述一致。 - **PostgreSQL**:使用 `EXCEPTION` 块(需在 `BEGIN...EXCEPTION...END` 中定义)。 - **Oracle**:通过 `EXCEPTION` 关键字和预定义异常(如 `NO_DATA_FOUND`)处理错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值