Brug en forberedt sætning, som lader dig parametrisere værdier, svarende til hvordan funktioner lader dig parameterisere variabler i sætningsblokke. Hvis du bruger MySQL Connector/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
Opret klasser til at håndtere databaseadgang og pak det ind i en metode, og resten af applikationen behøver ikke engang at vide, at en database bliver brugt.
Hvis du virkelig ønsker at bruge den gamle C API af en eller anden grund:
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);
Som du kan se, er Connector/C++ enklere. Det er også mindre fejltilbøjeligt; Jeg lavede sandsynligvis flere fejl ved at bruge C API end Connector/C++.
Se også:
- Udvikling af databaseapplikationer ved hjælp af MySQL Connector/C++
- Connector C++ i MySQL Forge-wikien