Mysql笔记-错误条件\处理程序
概念:
条件(Condition):定义需要捕获的错误类型(如 SQL 错误码、SQLSTATE 码或自定义错误名),是触发处理程序的“触发器”。
处理程序(Handler):当指定条件触发时,执行的一段 SQL 代码块(如回滚事务、记录日志、返回错误信息)。
1. 条件
1.1 作用
在 MySQL 中,条件(Condition) 是存储过程、函数、触发器中用于定义需要捕获的错误类型的核心机制。通过定义条件,可以精准触发后续的处理逻辑(如回滚事务、记录日志、跳过错误等),避免程序因未处理的异常而中断。通过过合理使用处理程序,可以增强数据库应用的健壮性,确保在出现异常情况时能够优雅地处理错误,而不是直接中断程序执行。
1.2 定义语法
使用:定义错误条件(变量),指向SQLSTATE,Mysql错误码,或者自定义条件名,便于后面处理程序使用。
作用域:在 MySQL 中,条件通过 DECLARE CONDITION 语句定义,必须在 BEGIN…END 块的最开始处声明(位于所有可执行语句之前),作用域仅限于当前块及其子块。
#定义条件
DECLARE condition_name CONDITION FOR {mysql_error_code | SQLSTATE 'sqlstate_value'};#定义处理程序--辅助这看怎么用,下面细讲
DECLARE {CONTINUE | EXIT} HANDLER FOR {condition_name | SQLSTATE 'code' | mysql_error_code | SQLWARNING | SQLEXCEPTION | NOT FOUND} BEGIN ... END;
定义条件示例:
-- 方法1:直接绑定MySQL错误码
DECLARE no_such_table CONDITION FOR SQLSTATE '42S02';-- 方法2:绑定数值错误码
DECLARE field_not_null CONDITION FOR 1048;-- 方法3:定义业务级条件
DECLARE insufficient_balance CONDITION FOR 'BALANCE_ERROR';
- SQLSTATE:遵循 ANSI SQL 标准,跨数据库兼容(如
42S02
在 Oracle 中同样表示表不存在)- 错误码:MySQL 特有扩展,细化到具体功能模块(如
1062
仅针对唯一键约束)MySQL_error_code是数值类型错误代码。sqlstate_value是长度为5的字符串类型错误代码。
在ERROR 1418 (HY000)中,1418是MySQL_error_code,'HY000’是sqlstate_value。
在ERROR 1142(42000)中,1142是MySQL_error_code,'42000’是sqlstate_value。
1.3 SQLSTATE 分类规则:
前两位数字 | 类别名称 | 含义 | 典型场景示例 |
---|---|---|---|
00 | 成功 | 操作成功完成 | 00000 (无错误) |
01 | 警告(WARNING) | 非致命问题,不影响事务完整性 | 数据截断、隐式类型转换 |
02 | 无数据(NOT FOUND) | 查询未返回结果 | SELECT 无匹配行 |
08 | 连接异常 | 数据库连接问题 | 网络中断、服务未启动 |
0A | 功能限制 | 数据库版本或配置不支持某些功能 | 不支持的字符集或存储引擎 |
20-26 | 数据异常(DATA) | 数据格式、类型或约束问题 | 主键冲突、无效日期格式 |
40 | 事务回滚 | 事务因错误自动回滚 | 死锁、超时 |
42 | 语法/规则违例 | SQL 语法错误或违反访问规则 | 关键字拼写错误、权限不足 |
HY | 通用错误 | MySQL 特有错误(非标准 SQLSTATE) | 表不存在(1146 )、权限拒绝(1044 ) |
2. 处理程序(Handler)
的处理程序(Handler)是存储过程和函数中实现错误控制的核心机制,通过预定义错误场景和对应的处理逻辑,开发者可以增强程序的健壮性。
2.1 定义语法
DECLARE handler_type HANDLER
FOR condition_value [, ...]
sp_statement;
- **
handler_type
**:处理策略(CONTINUE
/EXIT
/UNDO
)- **
condition_value
**:错误标识(SQLSTATE/错误码/条件名)- **
sp_statement
**:错误处理代码块
2.2 处理策略(handler_type
)
类型 | 行为 | 适用场景 |
---|---|---|
CONTINUE | 继续执行后续语句 | 可忽略的警告(如数据截断) |
EXIT | 终止当前块并回滚事务 | 关键操作失败(如主键冲突) |
UNDO | 回滚事务并撤销操作(Mysql暂不支持) | 需要事务回滚的业务场景 |
2.3 常见错误标识(condition_valu
)
类型/分类 | 定义 | 匹配规则 | 示例 |
---|---|---|---|
SQLSTATE | 5字符的字符串错误码,定义SQL标准错误类型 | 精准匹配5字符的SQLSTATE代码(区分大小写) | '02000' (查询无结果)、'23000' (外键冲突) |
MySQL_error_code | MySQL内部定义的数字型错误代码 | 精准匹配数值代码 | 1062 (主键冲突)、1146 (表不存在) |
错误名称 | 通过DECLARE ... CONDITION 自定义的命名错误条件 | 匹配自定义名称绑定的错误代码 | DECLARE my_error CONDITION FOR 1062; |
SQLWARNING | 警告类错误,表示非致命性问题 | SQLSTATE以01 开头 | '01000' (一般警告)、'01002' (数据截断) |
NOT FOUND | 无数据/未找到结果错误 | SQLSTATE以02 开头 | '02000' (SELECT无结果)、'02001' (游标结束) |
SQLEXCEPTION | 匹配所有没有被SQLWARNING或NOT FOUND捕获的SQLSTATE错误代码 | SQLSTATE不以00 (成功)、01 、02 开头 | '23000' (约束冲突)、'HY000' (通用错误) |
#方法1:捕获sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'NO_SUCH_TABLE';
#方法2:捕获mysql_error_value
DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'NO_SUCH_TABLE';
#方法3:先定义条件,再调用
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info = 'NO_SUCH_TABLE';
#方法4:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info = 'ERROR';
#方法5:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info = 'NO_SUCH_TABLE';
#方法6:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR';
2.4 处理语句:
如果出现上述条件之一,则采用对应的处理方式,并执行指定的处理语句。语句可以是
像“ SET 变量 = 值 ”这样的简单语句,也可以是使用 BEGIN ... END 编写的复合语句。
#创建一个名称为“InsertDataWithCondition”的存储过程,在存储过程中,定义处理程序,捕获sqlstate_value值,当遇到sqlstate_value值为23000时,执行EXIT操作,并且将@proc_value的值设置为-1。
DELIMITER //
CREATE PROCEDURE InsertDataWithCondition()
BEGIN
DECLARE duplicate_entry CONDITION FOR SQLSTATE '23000' ;
DECLARE EXIT HANDLER FOR duplicate_entry SET @proc_value = -1;
SET @x = 1;//假设department_name是unique的
INSERT INTO departments(department_name) VALUES('测试');
SET @x = 2;
INSERT INTO departments(department_name) VALUES('测试');
SET @x = 3;
END //
DELIMITER ;
#调用存储过程 查看x的值
CALL InsertDataWithCondition();