MySQL异常处理浅析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL异常处理浅析相关的知识,希望对你有一定的参考价值。

参考技术A mysql的异常处理分析如下:
标准格式
DECLARE
handler_type
HANDLER
FOR
condition_value[,...]
statement
handler_type:
CONTINUE
|
EXIT
|
UNDO
--这个暂时不支持
condition_value:
SQLSTATE
[VALUE]
sqlstate_value
|
condition_name
|
SQLWARNING
|
NOT
FOUND
|
SQLEXCEPTION
|
mysql_error_code
condition_value细节
1、常用MYSQL
ERROR
CODE
列表
http://dev.mysql.com/doc/refman/5.0/en/error-messages-server.html
更多错误列表见MySQL安装路径下
比如我的/usr/local/mysql/share/mysql/errmsg.txt
说明一下:SQLSTATE
[VALUE]
sqlstate_value这种格式是专门为ANSI
SQL

ODBC以及其他的标准.
并不是所有的MySQL
ERROR
CODE
都映射到SQLSTATE。
2、如果你不想插ERROR
CODE的话,就用速记条件来代替
SQLWARNING
代表所有以01开头的错误代码
NOT
FOUND
代表所有以02开头的错误代码,当然也可以代表一个游标到达数据集的末尾。
SQLEXCEPTION
代表除了SQLWARNING和NOT
FOUND
的所有错误代码
3、我们现在就用手册上的例子
CREATE
TABLE
t
(s1
int,primary
key
(s1));
mysql>
use
t_girl
Database
changed
mysql>
CREATE
TABLE
t
(s1
int,primary
key
(s1));
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
mysql>
mysql>
DELIMITER
||
mysql>
CREATE
PROCEDURE
handlerdemo
()
->
BEGIN
->
DECLARE
EXIT
HANDLER
FOR
SQLSTATE
'23000'
BEGIN
END;
--
遇到重复键值就退出
->
SET
@x
=
1;
->
INSERT
INTO
t
VALUES
(1);
->
SET
@x
=
2;
->
INSERT
INTO
t
VALUES
(1);
->
SET
@x
=
3;
->
END||
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
DELIMITER
;
mysql>
call
handlerdemo();
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
select
@x;
+------+
|
@x
|
+------+
|
2
|
+------+
1
row
in
set
(0.00
sec)
mysql>
call
handlerdemo();
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
select
@x;
+------+
|
@x
|
+------+
|
1
|
+------+
1
row
in
set
(0.00
sec)
mysql>
现在来看一下遇到错误继续的情况
mysql>
truncate
table
t;
Query
OK,
0
rows
affected
(0.01
sec)
mysql>
DELIMITER
$$
mysql>
DROP
PROCEDURE
IF
EXISTS
`t_girl`.`handlerdemo`$$
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
CREATE
DEFINER=`root`@`localhost`
PROCEDURE
`handlerdemo`()
->
BEGIN
->
DECLARE
CONTINUE
HANDLER
FOR
SQLSTATE
'23000'
BEGIN
END;
->
SET
@x
=
1;
->
INSERT
INTO
t
VALUES
(1);
->
SET
@x
=
2;
->
INSERT
INTO
t
VALUES
(1);
->
SET
@x
=
3;
->
END$$
Query
OK,
0
rows
affected
(0.01
sec)
mysql>
DELIMITER
;
mysql>
call
handlerdemo();
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
select
@x;
+------+
|
@x
|
+------+
|
3
|
+------+
1
row
in
set
(0.00
sec)
mysql>
call
handlerdemo();
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
select
@x;
+------+
|
@x
|
+------+
|
3
|
+------+
1
row
in
set
(0.00
sec)
mysql>
可以看到,始终执行到最后。
当然,上面的SQLSTATE
'23000'可以替换为1062
我们来看一下警告。
mysql>
alter
table
t
add
s2
int
not
null;
Query
OK,
0
rows
affected
(0.01
sec)
Records:
0
Duplicates:
0
Warnings:
0
此列没有默认值,插入的时候会出现警告或者1364错误提示。
mysql>
DELIMITER
$$
mysql>
DROP
PROCEDURE
IF
EXISTS
`t_girl`.`handlerdemo`$$
Query
OK,
0
rows
affected,
1
warning
(0.00
sec)
mysql>
CREATE
DEFINER=`root`@`localhost`
PROCEDURE
`handlerdemo`()
->
BEGIN
->
DECLARE
CONTINUE
HANDLER
FOR
1062
BEGIN
END;
->
DECLARE
CONTINUE
HANDLER
FOR
SQLWARNING
->
BEGIN
->
update
t
set
s2
=
2;
->
END;
->
DECLARE
CONTINUE
HANDLER
FOR
1364
->
BEGIN
->
INSERT
INTO
t(s1,s2)
VALUES
(1,3);
->
END;
->
SET
@x
=
1;
->
INSERT
INTO
t(s1)
VALUES
(1);
->
SET
@x
=
2;
->
INSERT
INTO
t(s1)
VALUES
(1);
->
SET
@x
=
3;
->
END$$
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
DELIMITER
;
mysql>
call
handlerdemo();
Query
OK,
0
rows
affected
(0.00
sec)
mysql>
select
*
from
t;
+----+----+
|
s1
|
s2
|
+----+----+
|
1
|
3
|
+----+----+
1
row
in
set
(0.00
sec)
遇到错误的时候插入的新记录。
mysql>
select
@x;
+------+
|
@x
|
+------+
|
3
|
+------+
1
row
in
set
(0.00
sec)

浅析c++异常

   异常处理:异常,让一个函数发现自己无法处理的错误时抛出异常,让函数的调用者直接或间接的处理这个问题。

传统错误处理办法

1、终止程序。(如段错误等)

2、返回错误码。

3、返回合法值,让程序处于某种非法的状态。(坑货)

4、调用一个预先设置的出现错误时调用的函数。

虽然可以解决问题,但都存在缺陷,然而引入异常处理可以很好的解决问题。

异常的抛出和捕获

1、异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个处理代码。

2、被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。

3、抛出异常后会释放局部存储对象,所以被抛出的对象也就还给系统了,throw表达式会初始化一个抛出特殊的异常对象副本(匿名对象),异常对象由编译管理,异常对象在传给对应的catch处理之后撤销。

栈展开

抛出异常的时候,将暂停当前函数的执行,开始查找对应的匹配catch子句,本层没找到时就不断向外层寻找,若到达main函数的栈,依旧没有匹配的,则终止程序。

找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。

具体实现如下:

#include<iostream>
using namespace std;
#include<string>

class Exception
{
public:
	Exception(int errId, const char* errMsg = "")
		:_errId(errId)
		, _errMsg(errMsg)
	{}
	void What()const
	{
		cout << "errId:" << _errId << endl;
		cout << "errMsg:" << _errMsg << endl;
	}
private:
	int _errId;//错误码
	string _errMsg;//错误信息
};
//异常的抛出
void Func1(bool isThrow)//抛出Exception对象
{
	if (isThrow)
		throw Exception(1, "抛出Exception对象");
	cout << "Func1->" << isThrow << endl;
}
void Func2(bool isThrowString,bool isThrowInt)//抛出string和int对象
{
	if (isThrowString)
		throw string("抛出string对象");
	if(isThrowInt)
		throw 7;
	cout << "Func2->" << isThrowString <<" "<<isThrowInt<< endl;
}

void Test()
{//异常的抛出
	try
	{   
		//Func1(true);Func2(true, true);此时只执行Func1(true),由于Func1()函数存在异常
		//同理针对下面程序,不执行Func2()的第二个参数的异常抛出
		//从调试中可以发现异常处理会跳出,造成程序执行中断
		Func1(false);
		Func2(true,true);
	}
	catch (const string& errMsg)
	{
		cout << "Catch string Object:" << errMsg << endl;
	}
	catch (int errId)
	{
		cout << "Catch int Object:" << errId << endl;
	}
	catch (const Exception& e)
	{
		e.What();
	}
	catch (...)
	{
		cout << "未知异常" << endl;
	}
	cout << "Func()" << endl;
}

异常的重新

有可能单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。

异常与构造函数&析构函数

1、构造函数完成对象的构造和初始化,需要保证不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化。

2、析构函数主要完成资源的清理,需要保证不要在析构函数内抛出异常,否则可能导致资源泄漏(内存泄漏、句柄未关闭等)

本文出自 “Materfer” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1754989

以上是关于MySQL异常处理浅析的主要内容,如果未能解决你的问题,请参考以下文章

Java异常总结和Spring事务处理异常机制浅析

浅析c++异常

JAVA异常处理原理浅析

C++ 浅析异常

SQL Server事务遭遇网络异常时的处理机制浅析

Windows结构化异常处理浅析