如何发送C++和MySQL动态MySQL查询

如何发送C++和MySQL动态MySQL查询,c++,mysql,C++,Mysql,使用VisualStudio、Windows7和mysql.h库 我要做的是发送一个MySQL查询,如下所示: mysql_query(conn, "SELECT pass FROM users WHERE name='Leo Tolstoy'"); 我唯一不能工作的就是发送一个查询,其中的名称不是上面显示的常量,而是一个从文本字段或其他任何内容获取的变量。那么我应该如何使用变量而不是常量呢 希望我能把我的问题说清楚。你不就用sprint或串接字符串或其他什么方法来构建查询字符串吗,这样当它到

使用VisualStudio、Windows7和mysql.h库

我要做的是发送一个MySQL查询,如下所示:

mysql_query(conn, "SELECT pass FROM users WHERE name='Leo Tolstoy'");
我唯一不能工作的就是发送一个查询,其中的名称不是上面显示的常量,而是一个从文本字段或其他任何内容获取的变量。那么我应该如何使用变量而不是常量呢


希望我能把我的问题说清楚。

你不就用sprint或串接字符串或其他什么方法来构建查询字符串吗,这样当它到达MySQL时,MySQL只看到SQL,而不知道常量来自何处?还是我遗漏了什么?

你不就是用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());
以下是一个例子:

#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());

使用一个准备好的语句,它允许您参数化值,类似于函数如何允许您参数化语句块中的变量。如果使用:

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

如果出于某种原因确实想使用旧的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 Forge wiki中
使用一个准备好的语句,它允许您参数化值,类似于函数如何允许您参数化语句块中的变量。如果使用:

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

如果出于某种原因确实想使用旧的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 Forge wiki中
一定是我遗漏了什么吗?我很喜欢你在这里展示的内容,但我发现了以下两个错误:错误C2065:“str”:未声明的标识符错误C2228:“.str”必须有类/结构/联合,我应该使用类还是什么?如果你不喜欢ostringstream,可以简化它:字符串查询=从用户处选择传递,其中name=”+name_value+”;mysql_queryconn,query.c_str;Hmmm.给出了另一个错误:错误C2664:“mysql_查询”:无法将参数2从“std::basic_string”转换为“const char*”,在尝试格式化之前的字符串并将字符串名称作为参数而不是在查询语句中添加此行时,我遇到了这种情况。@eimantaskaperiūnas:小心。直接在语句中插入值可能会导致注入攻击。它必须是аа或аа:我遗漏了什么吗?我很喜欢你在这里展示的内容,但我发现了以下两个错误:错误C2065:“str”:未声明的标识符错误C2228:“.str”必须有类/结构/联合,我应该使用类还是什么?如果你不喜欢ostringstream,可以简化它:字符串查询=从用户处选择传递,其中name=”+name_value+”;mysql_queryconn,query.c_str;Hmmm.给出了另一个错误:错误C2664:“mysql_查询”:无法将参数2从“std::basic_string”转换为“const char*”,在尝试格式化之前的字符串并将字符串名称作为参数而不是在查询语句中添加此行时,我遇到了这种情况。@eimantaskaperiūnas:小心。直接在语句中插入值会导致注入攻击。你是说这样?string query=从name='text'要添加的用户处选择id、密码;mysql_queryconn,querry;在此之后,我得到了以下错误:错误C2664:“mysql\u查询”:无法将参数2从“std::string”转换为“const char*”mysql\u queryconn,query.c\u str;你是说像这样?string query=从name='text'要添加的用户处选择id、密码;mysql_queryconn,querry;在此之后,我得到了以下错误:错误C2664:“mysql\u查询”:无法将参数2从“std::string”转换为“const char*”mysql\u queryconn,query.c\u str;sql::PreparedStatement*prep_stmt=con->prepareStatementINSERT到testid中,标签值@用户60627:不清楚你的意思。你有什么要补充的吗?您是否要求澄清?sql::PreparedStatement*prep_stmt=con->PrepareStatement插入testid,标签值@用户60627:不清楚你的意思。你有什么要补充的吗?你是否要求澄清?