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

sqlite3をc/c++で使う方法についてメモ。

以前ruby で sqlite を使う方法 - ぴょぴょぴょ? - Linuxとかプログラミングの覚え書き -でも書いたように、DBを使うアプリケーションは、通常はrubyなどのスクリプト言語で記述したほうが楽です。

でもc/c++からデータベースを使えると非常に便利です。

公式なリファレンスマニュアル

http://www.sqlite.org/capi3ref.htmlAPIの一覧があります

インストール

debian であれば libsqlite3-dev を入れるだけです.

 $ sudo apt-get update
 $ sudo apt-get install libsqlite3-dev

sqlite3 のAPI

よく使うAPIを列挙していきます

Database への接続

データーベースとして、 hogehoge.db というファイルを開きます。

const char *name="hogehoge.db";

sqlite3 *db=NULL;
int r = sqlite3_open(name, &db);
if (SQLITE_OK!=r){
   // open失敗
}

閉じる場合は

sqlite3_close(db);
SQLの実行

遅くてもいいので、とにかくSQLを実行したい場合は sqlite3_exec() を使うと楽です。

char *err=NULL;
sqlite3_exec(db, "create table tbl_test(id integer,name text);", NULL, NULL, &err);
 sqlite3_exec(db, "insert into tbl_test (id, name) values('123', 'hoge');", NULL, NULL, &err);

ただしsqlite3_exec() はクエリが完了するまで、呼び出し側スレッドを休眠させます。いわゆるブロッキング関数です。

パフォーマンスを重視する場合はクエリを非同期に実行する方法が有効です。非同期にクエリを実行するには以下のAPIを組み合わせて処理を記述します。

  1. sqlite3_prepare()を使って stmt を生成
  2. sqlite3_reset()を使って stmt の内部バッファをクリア
  3. 必要に応じて sqlite3_bind_??() でクエリを加工
  4. sqlite3_step() を使って クエリを実行
  5. sqlite3_finalize() を使って stmt を開放

使用例は以下のようになります。

// stmt を生成する
const char *sql = "insert into tbl_test (id, name) values('?', '?');";
sqlite3_stmt *stmt=NULL;
sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);

// stmtの内部バッファを一旦クリア
sqlite3_reset(stmt);

// sqlの?の部分に、値を設定
int id=123;
const char *name="hoge";
sqlite3_bind_int(stmt, 0,  id);
sqlite3_bind_text(stmt, 1,  name);

// stmtのSQLを実行
int loop=0;
while (SQLITE_DONE != sqlite3_step(stmt)){
    if (loop++>1000){
        // エラー
    }
}

// stmt を開放
sqlite3_finalize(stmt);

かなり面倒です。クエリの実行はsqlite3_step() で行われます。返り値は、以下の値をとります。

  • SQLITE_ERROR:クエリが何らかの理由によりエラーとなった場合
  • SQLITE_ROW: クエリの結果が列として取れる場合
  • SQLITE_BUSY: クエリが未完の場合
  • SQLITE_DONE: クエリが完了時

sqite3_step() は非同期にクエリを実行するので、上記返り値を使ったDBと同期を取るようなコーディングが必須となります。

SQLの実行結果の取得方法 (select文のつかいかた)
// stmt を生成する
const char *sql = "select id, name from tbl_test";
sqlite3_stmt *stmt=NULL;
sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);

// stmtの内部バッファを一旦クリア
sqlite3_reset(stmt);

// stmtのSQLを実行し、結果を一列づつ取得
int r;
while (SQLITE_ROW == (r=sqlite3_step(stmt))){
   int  id = sqlite3_column_int(stmt, 0);
  const char *name = sqlite3_column_text(stmt, 1);
}
if (SQLITE_DONE!=r){
   // エラー
}

// stmt を開放
sqlite3_finalize(stmt);
エラー処理
  • APIの返り値を毎回確認しましょう (ToT)
トランザクション transaction

専用のAPIは用意されていません。

SQLの begin, commit 文を個別に sqlite3_exec()で発行します。

sqlite3_exec(db, "begin;", NULL, NULL, NULL);
sqlite3_exec(db, "commit;", NULL, NULL, NULL);
バッチ処理

スクリプトで書いたほうが楽なので、割愛します。


SQLite入門 すぐに使える軽快・軽量データベース・エンジン
西沢 直木
翔泳社
売り上げランキング: 68520
おすすめ度の平均: 4.0
4 初心者向け
5 SQLの入門に最適
5 DB連携の本格Webプログラム入門書としても最適
4 SQLiteの入門には最適
3 題名どおりSQLiteの入門にはいいんじゃないでしょうか