Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak wysyłać dynamiczne zapytania mysql C++ i mysql

Użyj przygotowanej instrukcji, która umożliwia parametryzację wartości, podobnie jak funkcje umożliwiają parametryzację zmiennych w blokach instrukcji. Jeśli używasz 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

Utwórz klasy do obsługi dostępu do bazy danych i zapakuj to w metodę, a reszta aplikacji nie musi nawet wiedzieć, że baza danych jest używana.

Jeśli z jakiegoś powodu naprawdę chcesz użyć starego 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);

Jak widać, Connector/C++ jest prostszy. Jest również mniej podatny na błędy; Prawdopodobnie popełniłem więcej błędów używając C API niż Connector/C++.

Zobacz też:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rekurencja MySQL?

  2. Optymalizacja wydajności zapytań w MySQL

  3. Warunkowe wstawianie MySQL przy duplikacie

  4. Dlaczego moja procedura składowana zgłasza błąd „Brak danych — pobrano, wybrano lub przetworzono zero wierszy”, gdy w instrukcji znajduje się WHERE?

  5. Obsługa przejściowych awarii w .net core 2.1 MVC dla bazy danych MySQL