【问题标题】:Catch MySQL error in c++在 C++ 中捕获 MySQL 错误
【发布时间】:2012-09-18 12:20:38
【问题描述】:

在 C++ 中,我正在使用 mysql.h 库,但无法捕获 MySQL 错误(例如,由于主键冲突而导致插入失败)。

我试过了

#include <mysql.h>
// ...
try{
    res = mysql_perform_query(conn, sqlIn);
} catch (...) {
// ...
}

但它仍然无法避免中止:

MySQL query error : Duplicate entry

我正在使用 PuTTy 接口运行已编译的 c++ 程序,当程序中止时,它会重现 MySQL 的错误(无论我是否使用 TRY CATCH)。
我没有找到任何对 MySQL 使用 catch 语句的特定异常代码的引用。

显然,即使使用“一揽子”语法 (catch (...)),C++(使用此库 mysql.h)也不会捕获 MySQL 回调错误。由于这种语法应该捕获所有异常,但在这种情况下没有,我不知道这里发生了什么。如何捕获 SQL 异常?

【问题讨论】:

  • 如果你没有捕捉到异常,你怎么知道那是失败信息?
  • @hmjd 我正在使用 PuTTy 接口运行已编译的 c++ 程序,当程序中止时,它会重现 MySQL 的错误(无论我是否使用 TRY CATCH)。
  • 您是否尝试在调用 MySQL 之间调用 mysql_errno()?如果您没有处理 SQL 错误(此处不讨论异常),然后继续调用更多 MySQL 代码,则 MySQL 可能会像 exit(1) 那样中止应用程序。
  • 我以为mysql的接口是C的,所以应该不会抛出异常吧。

标签: c++ exception-handling mysql-error-1062


【解决方案1】:

mysql C 库不会抛出任何异常;它只是像大多数其他 C 库一样,在一个公共位置(如 errno)设置错误信息并返回一个状态。由您的客户端代码检查返回并引发错误/异常。

如果您需要轻松解决问题,请尝试使用 mysql++ (AKA mysqlpp)。 这是一款我可以担保的软件;坚如磐石! http://tangentsoft.net/mysql++/

【讨论】:

  • 我正在认真考虑更改库。我不知道必要重构的影响。我想我会尝试 mysql++ - 你知道我可以使用 mysql++ 库而不是 mysql.h 来捕获 mysql 错误吗?
  • 是的,我确定; 100% 可能!阅读tangentsoft.net/mysql++/doc/html/userman/tutorial.html 页上的“3.4. 例外”部分。事实上,它支持两种用例;例如,如果您不希望从代码的一部分中引发异常,则可以使用NoExceptions 类在其范围内暂时关闭异常。祝你好运!
【解决方案2】:

尝试在 mysql C 库周围使用一些 c++ 包装器。例如http://mysqlcppapi.sourceforge.net/

C 不会抛出你必须通过 mysql_errorno 函数检查的异常。

【讨论】:

  • 您获得了投票,因为包装器的概念是正确的,并且您是第一个建议使用包装器的人。我无法使用这个包装器找到我的方式,最终使用了 mysql++(因此将赏金授予@kingstonian)。非常感谢。
【解决方案3】:

我不会推荐 Mysql C++ 库有两个原因 1.很难得到支持。 2.比Mysql C库慢

您可以使用 mysql_error() 和 mysql_errno() API 来了解错误并手动处理异常

【讨论】:

  • 是的,性能是一个关键问题。 mysql_error() 的问题是我无法捕获它。当我尝试查询(使用重复的唯一键)时,程序中止。有什么建议吗?
  • 你可以使用 mysql_errno() 来捕获错误,请参考下面的示例 try { if(mysql_query(QUERY) != SUCCESS) { int mysql_error_num = mysql_errno();抛出 mysql_error_num ; } } 捕捉 (int) { ...... ...... }
  • 我通过 mysqlpp 包装器使用它。没有比较开销时间,但运行了每分钟 60K 连接/线程的模拟并且没有崩溃。
  • 现在,你能捕捉到重复的条目吗?
【解决方案4】:

根据 kingstonian 的建议,我使用 mysql++ 包装 mysql(用于在 ubuntu 中安装,see my recipe answering another SO question

下面的代码用于测试错误处理,其中在键中插入了一个重复值 (Id_Target = 9)。使用适合您的数据库结构的插入来适应您自己的需求。

#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include </usr/include/mysql++/mysql++.h>


// sudo g++ -o /temp/zdelMySQLpp01c $(mysql_config --cflags) /home/ubuntu/zdelMySQLpp01c.cpp $(mysql_config --cflags --libs) -l pthread -std=c++0x -g -L/usr/lib/mysql -lmysqlclient -lmysqlpp

using namespace mysqlpp;
using namespace std;

//MySQL type
struct connection_details {
        char *server;
        char *user;
        char *password;
        char *database;
};

int main(int argv, char** argc){

// MySQL connection (global)
struct connection_details mysqlD;
mysqlD.server = (char *)"localhost";  // where the mysql database is
mysqlD.user = (char *)"root";       // the root user of mysql   
mysqlD.password = (char *)"XXXXXX"; // the password of the root user in mysql
mysqlD.database = (char *)"test";   // the databse to pick

// connect to the mysql database
mysqlpp::Connection conn(false);
if (conn.connect(mysqlD.database, mysqlD.server, mysqlD.user, mysqlD.password)) {
    //printf("ALOALO funcionou conexao\n");
    mysqlpp::Query query = conn.query("INSERT INTO test.target (Id_Target, Ds_Target, Ds_Target_Name, Ds_Target_PWD, Ds_Target_Email, Ds_Target_Icon) VALUES ('9', 'test', 'name', 'pass', 'email', NULL)");
        if (mysqlpp::StoreQueryResult res = query.store()) {
                cout << "We have:" << endl;
                for (size_t i = 0; i < res.num_rows(); ++i) {
                    cout << '\t' << res[i][0] << endl;
                }
        } else {
                cerr << "Failed to get item list: " << query.error() << endl;
                return 1;
    }
        return 0;
}
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-26
    • 2015-10-09
    • 2010-10-07
    • 2012-01-16
    • 2012-10-10
    • 2010-11-23
    • 2013-03-14
    • 1970-01-01
    相关资源
    最近更新 更多