Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment envoyer des requêtes mysql dynamiques C++ et mysql

Utilisez une instruction préparée, qui vous permet de paramétrer des valeurs, de la même manière que les fonctions vous permettent de paramétrer des variables dans des blocs d'instructions. Si vous utilisez Connecteur 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

Créez des classes pour gérer l'accès à la base de données et encapsulez-les dans une méthode, et le reste de l'application n'a même pas besoin de savoir qu'une base de données est utilisée.

Si vous voulez vraiment utiliser l'ancienne API C pour une raison quelconque :

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

Comme vous le voyez, Connector/C++ est plus simple. Il est également moins sujet aux erreurs ; J'ai probablement fait plus d'erreurs en utilisant l'API C que Connector/C++.

Voir aussi :