c/c++で MySQL を使う方法

c/c++mysql のデータベースへアクセスする方法をまとめます。

rubyphpと比べるとc/c++でのコーディングはかなり面倒ですが、うまく記述できればパフォーマンスがかなり向上できるようです。

参考URL

DBへの接続

#include <mysql.h>

MYSQL mysql;
mysql = mysql_init(NULL);
if (NULL==mysql) {
  // 初期化失敗
}
const char *hostname = NULL;
const char *username = "user";
const char *password = "pass";
const char *database = "database-name";
unsigned long portnumber = 0;
if (NULL==mysql_real_connect(mysql, hostname, username, database, portnumber, NULL, 0) {
  // 接続エラー
   printf("error: %s\n", mysql_error(mysql));
} else {
  //  接続成功
}

クエリの発行

int r;
r = mysql_query(mysql, "CREATE TABLE hoge (id integer)" );
if (r) {
   // 失敗
   printf("error: %s\n", mysql_error(mysql));
} else {
   // 成功
}

Prepared Statement の作成

  const char *query = "SELECT * FROM HOGEHOGE WHERE ID = ?";

  MYSQL_STMT *stmt = mysql_stmt_init(mysql);
  if (!stmt) {
     // 失敗時
  }
  int r;
  r = mysql_stmt_prepare(stmt, query, strlen(query));
  if (r) {
     // 失敗時
  }

Prepared Statement へのパラメータの設定

MYSQL_BIND 構造体の配列を用意し、各要素にパラメータを保存している変数のポインタを渡す。たとえば int 型の変数 value の値を bind したい場合は、以下のとおり。

  int value = 1234;

  MYSQL_BIND bind[1];
  bind[0].buffer_type = MYSQL_TYPE_LONG;
  bind[0].buffer = &value;
  bind[0].is_null = 0;

  if (mysql_stmt_bind_param(stmt, bind)) {
     // エラー処理
     printf("error: %s\n", mysql_stmt_error(stmt));
  }

Prepared Statement の出力先バッファの設定

SELECT 文等の結果を返すクエリを発行する場合は、mysql_stmt_bind_result関数を使ってあらかじめ結果の保存先メモリ領域を設定しておく。

まずPrepared Statementの出力のカラム数 num_fields を求める。

MYSQL_RES *res = mysql_stmt_result_metadata(stmt);
assert(res);
int num_fields = mysql_num_fields(res);
mysql_free_result(res);

次に num_fields 個の MYSQL_BIND を用意し、それぞれにバッファを割り当てる。

たとえば、0 番目のカラムの出力を、int型の変数 output に保存する場合は、

  int output ;

  MYSQL_BIND result[num_fields];
  result[0].buffer_type = MYSQL_TYPE_LONG;
  result[0].buffer = &output;
  result[0].is_null = 0;

となる。 同様に、配列resultの全要素を設定したら、最後に

  if (mysql_stmt_bind_result(stmt, result)) {
     // エラー処理
     printf("error: %s\n", mysql_stmt_error(stmt));
  }

で、バッファを stmt に設定する。

Prepared Statement の実行

実行は、mysql_stmt_execute(stmt) を呼ぶだけ。

  if (mysql_stmt_execute(stmt)) {
     // エラー処理
     printf("error: %s\n", mysql_stmt_error(stmt));
  }

MYSQL_BIND で 変数 value を stmt にバインドしてあるので、
パラメータを変更しながらクエリを繰り返し発行するときは、

   value = 1;
   mysql_stmt_execute(stmt);
   value = 2;
   mysql_stmt_execute(stmt);

とすれば良い。

Prepared Statement の結果の取得

レコードを一つづつfetchしていく。こちらも 変数
output を stmt にバインドしてあるため、以下のような簡潔なコードで記述できる。

int r;
while ( (r = mysql_stmt_fetch(stmt)) == 0 ) {
     printf("output: %d\n", output);  
}
if (MYSQL_NO_DATA != r) { 
     // エラー処理
     printf("error: %s\n", mysql_stmt_error(stmt));
}

NUL の扱い

mysql_stmt_bind_param() で NULL を指定するには

 bind[0].buffer_type = MYSQL_TYPE_NULL;

とする。

mysql_stmt_bind_result() で NULL を取得したい場合は

 my_bool isNull;
 bind[0].is_null = &isNull;

MYSQL_BIND の is_null メンバを使う。

現場で使える MySQL (DB Magazine SELECTION)
松信 嘉範
翔泳社
売り上げランキング: 71115
おすすめ度の平均: 5.0
5 よいです。
5 ODBC接続など実用的な内容
5 実践的な良書、作者の今後にも期待
4 システム管理者向け

実践ハイパフォーマンスMySQL 第2版
Baron Schwartz Peter Zaitsev Vadim Tkachenko Jeremy D. Zawodny Arjen Lentz Derek J. Balling
オライリージャパン
売り上げランキング: 1133