LoginSignup
45

More than 5 years have passed since last update.

C++ から MySQL に接続する

Last updated at Posted at 2016-10-14

はじめに

本記事は Hatena Blog に投稿した以下の記事について再びまとめたものになります.

C++ から MySQL のデータベースに接続する

思った以上にアクセスが伸びていたため,より分かりやすい形式で Qiita に投稿しようと思いました.

内容はあまり変更せず,(1)MySQL への接続方法と(2)データベースに対する操作についてまとめます.

詳しくは以下の Document を参照していただければと思います.

MySQL

MySQL はオープンソースで公開されている RDBMS の1つです.

C++ のプログラムから MySQL に接続するには Connector/C++ を用います.
以下のリンクからダウンロード可能なので,OS に応じて適切なものを選択してください.

また,本記事では MySQL と Connector/C++ のインストール方法や,SQL 構文については省略します.

Connector/C++

それでは C++ のプログラムから MySQL に接続する方法を解説していきます.

処理の流れの概要は次の通りになります.

  1. ドライバの生成

  2. ドライバを用いてデータベースに接続

  3. データベースに対して処理を行う

1 と 2 は API を用いて各1行で記述することができるため,3 の処理について詳しく解説したいと思います.

まず,実際に Connector/C++ で MySQL に対して処理を行うプログラムを添付します.

connect_mysql.cpp
#include <iostream>
#include <sstream>
#include <memory>
#include <mysql_driver.h>
#include <mysql_connection.h>
#include <mysql_error.h>
#include <cppconn/Statement.h>
#include <cppconn/ResultSet.h>

//define your own configurations in mysql_config.hpp
//for example: HOST = "tcp://127.0.0.1:3306", USER = "root", PASSWORD = "password"
//             DATABASE = "database_name"
#include "mysql_config.hpp"
using namespace std;

int main()
{
    try {
        sql::mysql::MySQL_Driver *driver = sql::mysql::get_mysql_driver_instance();
        unique_ptr<sql::Connection> con(driver->connect(HOST, USER, PASSWORD));
        unique_ptr<sql::Statement> stmt(con->createStatement());


        stmt->execute("USE " + DATABASE);
        stmt->execute("DROP TABLE IF EXISTS conference");
        stmt->execute("CREATE TABLE conference(cid int, name varchar(10))");
        cout << "\"conference\" table has been created." << endl;

        stmt->execute("INSERT INTO conference VALUES(1, 'SIGMOD')");
        stmt->execute("INSERT INTO conference VALUES(2, 'VLDB')");
        stmt->execute("INSERT INTO conference VALUES(3, 'ICDE')");
        stmt->execute("INSERT INTO conference VALUES(4, 'KDD')");

        unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT * FROM conference"));

        size_t row = 0;
        while (res->next()) {
            cout << row << "\t";
            /* You can use either numeric offsets... */
            cout << "cid = " << res->getInt(1);
            /* ... or column names for accessing results. The latter is recommended. */
            cout << ", name = '" << res->getString("name") << "' " << endl;
            row++;
        }

    } catch (sql::SQLException &e) {
        cout << "# ERR: SQLException in " << __FILE__ << " on line " << __LINE__ << endl;
        cout << "# ERR: " << e.what() << endl;
        cout << " (MySQL error code: " << e.getErrorCode();
        cout << ", SQLState: " << e.getSQLState() << " )" << endl;
        return EXIT_FAILURE;
    } catch (runtime_error &e) {
        cout << "# ERR: runtime_error in " << __FILE__ << " on line " << __LINE__ << endl;
        cout << "# ERR: " << e.what() << endl;
        return EXIT_FAILURE;
    }
}

このプログラムはデータベースに以下に示すテーブルを作成し,全ての要素を取得するものになっています.

cid name
1 SIGMOD
2 VLDB
3 ICDE
4 KDD

具体的には,conference TABLE を CREATE し,4つの VALUES を INSERT します.

最後にすべての要素を SELECT し,データを列挙します.

ドライバの生成とデータベースへの接続

ドライバの生成はプログラムの19行目,データベースへの接続は20行目で行っています.

19: sql::mysql::MySQL_Driver *driver = sql::mysql::get_mysql_driver_instance();
20: unique_ptr<sql::Connection> con(driver->connect(HOST, USER, PASSWORD));

get_mysql_driver_instance() によってドライバを生成し,取得したドライバを用いて connect() でデータベースへと接続しています.

(connect() の戻り値である sql::Connection は最終的に解放する必要があるため,ここでは unique_ptr を使用しています.)

データベースに対して処理を行う

データベースに対する処理は大きく分けて,(1)結果が返ってこない処理,(2)結果が返ってくる処理の2つに分類することができます.

(1)は INSERT,(2)は SELECT といった処理が該当します.

Connector/C++ では(1)と(2)について,それぞれ execute() 関数と executeQuery() 関数を用いて実行します.

まず前準備として,sql::Statement インスタンスを生成します.

unique_ptr<sql::Statement> stmt(con->createStatement());

execute() と executeQuery() は sql::Statement のメンバ関数なので,以降の処理は stmt から実行します.

execute()

execute() 関数を用いてテーブルの作成,データの挿入を行う例について説明します.

上記のプログラムでは 24~32 行目に該当します.

stmt->execute("USE " + DATABASE);
stmt->execute("DROP TABLE IF EXISTS conference");
stmt->execute("CREATE TABLE conference(cid int, name varchar(10))");
cout << "\"conference\" table has been created." << endl;

stmt->execute("INSERT INTO conference VALUES(1, 'SIGMOD')");
stmt->execute("INSERT INTO conference VALUES(2, 'VLDB')");
stmt->execute("INSERT INTO conference VALUES(3, 'ICDE')");
stmt->execute("INSERT INTO conference VALUES(4, 'KDD')");

前半4行がテーブルの作成,後半4行がデータの挿入です.

execute() 関数の引数には SQL クエリをそのまま記述することができます.

executeQuery()

続いて,executeQuery() 関数を用いてデータの取得をする例について説明します.

上記プログラムでは 34~44 行目に該当します.

unique_ptr<sql::ResultSet> res(stmt->executeQuery("SELECT * FROM conference"));

size_t row = 0;
while (res->next()) {
    cout << row << "\t";
    /* You can use either numeric offsets... */
    cout << "cid = " << res->getInt(1);
    /* ... or column names for accessing results. The latter is recommended. */
    cout << ", name = '" << res->getString("name") << "' " << endl;
    row++;
}

executeQuery() を実行すると,sql::ResultSet インスタンスが返されます.

このとき,execute() と同様に executeQuery() の引数には SQL クエリをそのまま記述することができます.

取得したデータへのアクセスは, getXX() 関数を用います.

このプログラムの例ですと,Int 型の cid と String 型の name の2つの要素があるため,それぞれ getInt() と getString() を用いて結果を取得します.

また,getInt() の引数は列番号であり,getString() の引数は attribute 名を指定します.
※列番号は 1 から始まります.

まとめ

Connector/C++ を用いて MySQL に接続する方法を,実際にプログラムを用いて紹介しました.

処理の流れの概要は,

  1. ドライバの生成
  2. データベースに接続
  3. データベースに処理を行う

でした.

1 と 2 に関しては API を用いて簡単に記述でき,3 の処理に関しても execute() や executeQuery() 関数に SQL クエリを渡すことによって簡単に実行することができました.

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
45