如何用c++和mysql发送动态的mysql查询

How to send C++ and mysql dynamic mysql queries

本文关键字:mysql 动态 查询 c++ 何用      更新时间:2023-10-16

使用Visual Studio, Windows 7和mysql.h库。

我要做的是像这样发送一个MySQL查询:

mysql_query(conn, "SELECT pass FROM users WHERE name='Leo Tolstoy'");

我唯一不能得到的工作是发送一个查询,其中的名称将不是一个常量,因为它如上所示,而是一个变量从文本字段或其他任何东西。那么我应该如何使用变量而不是常量呢?

希望我把问题讲清楚了。

使用一个准备好的语句,它允许您参数化值,类似于函数允许您在语句块中参数化变量。如果使用MySQL连接器/c++:

// use std::unique_ptr, boost::shared_ptr, or whatever is most appropriate for RAII
// Connector/C++ requires boost, so 
std::unique_ptr<sql::Connection> db;
std::unique_ptr<sql::PreparedStatement> getPassword
std::unique_ptr<sql::ResultSet> result;
std::string name = "Nikolai Gogol";
std::string password;
...
getPassword = db->prepareStatement("SELECT pass FROM users WHERE name=? LIMIT 1");
getPassword->setString(1, name);
result = getPassword->execute();
if (result->first()) {
    password = result->getString("pass");
} else {
    // no result
    ...
}
// smart pointers will handle deleting the sql::* instances

创建类来处理数据库访问,并将其封装在方法中,应用程序的其余部分甚至不需要知道正在使用数据库。

如果你真的想使用旧的C API:

MYSQL *mysql;
...
const my_bool yes=1, no=0;
const char* getPassStmt = "SELECT password FROM users WHERE username=? LIMIT 1";
MYSQL_STMT *getPassword;
MYSQL_BIND getPassParams;
MYSQL_BIND result;
std::string name = "Nikolai Gogol";
std::string password;
if (! (getPassword = mysql_stmt_init(mysql))) {
    // error: couldn't allocate space for statement
    ...
}
if (mysql_stmt_prepare(getPassword, getPassStmt, strlen(getPassStmt))) {
    /* error preparing statement; handle error and 
       return early or throw an exception. RAII would make
       this easier.
    */
    ...
} else {
    unsigned long nameLength = name.size();
    memset(&getPassParams, 0, sizeof(getPassParams));
    getPassParams.buffer_type = MYSQL_TYPE_STRING;
    getPassParams.buffer = (char*) name.c_str();
    getPassParams.length = &nameLength;
    if (mysql_stmt_bind_param(getPassword, &getPassParams)) {
        /* error binding param */
        ...
    } else if (mysql_stmt_execute(getPassword)) {
        /* error executing query */
        ...
    } else {
        // for mysql_stmt_num_rows()
        mysql_stmt_store_result(getPassword);
        if (mysql_stmt_num_rows(getPassword)) {
            unsigned long passwordLength=0;
            memset(&result, 0, sizeof(result));
            result.length = &passwordLength;
            mysql_stmt_bind_result(getPassword, &result);
            mysql_stmt_fetch(getPassword);
            if (passwordLength > 0) {
                result.buffer = new char[passwordLength+1];
                memset(result.buffer, 0, passwordLength+1);
                result.buffer_length = passwordLength+1;
                if (mysql_stmt_fetch_column(getPassword, &result, 0, 0)) {
                    ...
                } else {
                    password = static_cast<const char*>(result.buffer);
                }
            }
        } else {
            // no result
            cerr << "No user '" << name << "' found." << endl;
        }
    }
    mysql_stmt_free_result(getPassword);
}
mysql_stmt_close(getPassword);
mysql_close(mysql);

如您所见,Connector/c++更简单。它也更不容易出错;在使用C API时,我可能比Connector/c++犯了更多的错误。

参见:

    使用MySQL连接器/c++开发数据库应用程序
  • Connector c++ in MySQL Forge wiki

难道你不只是构建查询字符串,使用sprint或连接字符串或其他什么,所以当它到达MySQL时,MySQL只是看到SQL,不知道常量来自哪里?还是我错过了什么?

下面是一个例子:

#include <sstream>
#include <string>
#include <iostream>
using namespace std;
/// ...
string name_value = "Leo Tolstoy";
ostringstream strstr;
strstr << "SELECT pass FROM users WHERE name='" << name_value << "'";
string str = strstr.str();
mysql_query(conn, str.c_str());