在MySQL中,特定的异常需要特定的处理。这些异常可能与错误以及子例程中的一般流程控制有关。定义异常就是预先定义程序执行过程中遇到的问题。异常处理定义了遇到问题时应该采取的处理方式,保证存储过程或函数在遇到错误或警告时能够继续执行。1异常定义1.1语法DECLAREcondition_nameCONDITIONFOR[condition_type];1.2说明condition_name参数表示异常的名称;condition_type参数表示条件的类型,condition_type由SQLSTATE[VALUE]sqlstate_value|mysql_error_code组成:sqlstate_value和mysql_error_code都可以表示MySQL错误;sqlstate_value为lengthstring类型的错误码为5;mysql_error_code为数值类型的错误码;1.3示例定义“ERROR1148(42000)”错误,名称为command_not_allowed。有两种方法:方法一:使用sqlstate_valueDECLAREcommand_not_allowedCONDITIONFORSQLSTATE'42000';方法二:使用mysql_error_codeDECLAREcommand_not_allowedCONDITIONFOR1148;2自定义异常处理2.1异常处理语法DECLAREhandler_typeHANDLERFORcondition_value[,...]sp_statement_type参数说明handler2.2|EXIT|UNDOhandler_type为错误处理方式,参数为3个取值之一;CONTINUE表示不处理错误,继续执行;EXIT表示遇到错误立即退出;UNDO表示遇到错误后撤销之前的操作,目前不支持MySQLRollback操作;条件值:SQLSTATE[VALUE]sqlstate_value|condition_name|SQLWARNING|NOTFOUND|SQLEXCEPTION|mysql_error_codecondition_value表示错误类型;SQLSTATE[VALUE]sqlstate_value是一个包含5个字符的字符串错误值;condition_name表示DECLARECONDITION定义的错误条件名称;SQLWARNING匹配所有以01开头的SQLSTATE错误码;NOTFOUND匹配所有以02开头的SQLSTATE错误代码;SQLEXCEPTION匹配所有未被SQLWARNING捕获或NOTFOUND的SQLSTATE错误代码;mysql_error_code匹配数字类型的错误代码;2.3异常捕获方法方法一:捕获sqlstate_value异常该方法是捕获sqlstate_value值。如果sqlstate_value值为“42S02”,则执行CONTINUE操作,输出“NO_SUCH_TABLE”消息DECLARECONTINUEHANDLERFORSQLSTATE'42S02'SET@info='NO_SUCH_TABLE';方法二:捕获mysql_error_code异常这种方法是捕获mysql_error_code的值。如果mysql_error_code的值为1146,则执行CONTINUE操作,输出“NO_SUCH_TABLE”信息;DECLARECONTINUEHANDLERFORNO_SUCH_TABLESET@info='NO_SUCH_TABLE';方法三:先定义条件,再捕获异常DECLAREno_such_tableCONDITIONFOR1146;DECLARECONTINUEHANDLERFORNO_SUCH_TABLESET@inf'使用SQLWARNING捕获异常DECLAREEXITHANDLERFORSQLWARNINGSET@info='ERROR';方法五:使用NOTFOUND捕捉异常DECLAREEXITHANDLERFORNOTFOUNDSET@info='NO_SUCH_TABLE';方法六:使用SQLEXCEPTION捕获异常DECLAREEXITHANDLERFORSQLEXCEPTIONSET@info='ERROR';设置表的主键,在没有定义异常处理和定义异常处理的情况下,看执行了哪一步。showdatabases;usewms;createtablelocation(location_idintprimarykey,location_namevarchar(50));例1:DELIMITER//CREATEPROCEDUREhandlerInsertNoException()BEGIN/*DECLARECONTINUEHANDLERFORSQLSTATE'23000'SET@x2=1;*/SET@x=1;INSERTINTOlocation(1,'北京');SET@x=2;INSERTINTOlocationVALUES(1,'无锡');SET@x=3;END;//DELIMITER;调用存储过程及结果:mysql>callhandlerInsertNoException();ERROR1062(23000):Duplicateentry'1'forkey'PRIMARY'mysql>select@x;+-----+|@x|+------+|2|+------+1rowinset(0.00sec)mysql>select*fromlocation;+------------+---------------+|location_id|location_name|+-------------+----------------+|1|北京|+------------+-----------------+1rowinset(0.00sec)注意:操作实例2前,必须清空表中的数据,并登出并重新登录,避免客户端变量@x的影响。详情见结语中的***。mysql>truncatetablelocation;QueryOK,0rowsaffected(0.04sec)mysql>select*fromlocation;Emptyset(0.00sec)mysql>exit;Byedavid@Louis:~$mysql-uroot-pEnterpassword:WelcometotheMySQLmonitor.Commandsendwith;or\g.YourMySQLconnectionidis53.Serverversion:538-0ubuntu0.14.04.1(Ubuntu)mysql>usewms;ReadingtableinformationforcompletionoftableandcolumnnamesYoucanturnoffthisfeaturetogetaquickerstartupwith-ADatabasechangedmysql>select*fromlocation;Emptyset(0.00sec)mysql>select@x;+------+|@x|+------+|NULL|+------+1rowinset(0.00sec)例2:定义异常处理时:DELIMITER//CREATEPROCEDUREhandlerInsertWithException()BEGINDECLARECONTINUEHANDLERFORSQLSTATE'23000'SET@x2=1;SET@x=1;INSERTINTOlocationVALUES(1,'北京');SET@x=2;INSERTINTOlocationVALUES(1,'无锡');SET@x=3;END;//DELIMITER;调用存储过程和结果:mysql>CALLhandlerInsertWithException();QueryOK,0rowsaffected(0.09sec)mysql>select@x;+------+|@x|+------+|3|+------+1rowinset(0.00sec)说明和结论:1、在MySQL中,@var_name代表一个用户变量,用SET语句来赋值值,用户变量与连接有关,一个客户端定义的变量不能被其他客户端看到或使用当客户端退出时,所有连接到该客户端的变量都会自动释放。2、例1中,由于异常声明“”被注释掉,所以向表中插入相同的主键会触发异常,走默认(EXIT)路径;并查看此时@x返回2,说明后面的INSERT语句没有执行就退出了。3.定义了异常处理。如果此时遇到错误,则继续按照异常定义的方式执行;但只有第一条数据被插入到表中。此时用户变量@x=3表示执行到结束;
