sql >> データベース >  >> RDS >> Mysql

C++およびmysqlの動的mysqlクエリを送信する方法

    関数でステートメントブロックの変数をパラメーター化するのと同様に、プリペアドステートメントを使用して値をパラメーター化できます。 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
    

    データベースアクセスを処理するクラスを作成し、それをメソッドでラップします。アプリケーションの残りの部分は、データベースが使用されていることを知る必要さえありません。

    何らかの理由で古いCAPIを本当に使用したい場合:

    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++の方が簡単です。また、エラーが発生しにくくなります。おそらく、Connector /C++よりもCAPIを使用して多くの間違いを犯しました。

    参照:



    1. 1つのテーブルから別のテーブルにデータを保存できません

    2. Django1.7の長い移行は決して終わらない

    3. JavaInstantをMySQLデータベースに保存する方法

    4. jdbcプールで接続を強制的に再利用するにはどうすればよいですか?