SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

SQLiteで“おこづかいちょう”

SQLite、C++/CLI、C#で実用(?)アプリケーションを作る


結果の取得とUnicode

クエリ結果の取得

 SQL文がSELECTのように複数(0個以上)の結果を返すとき、sqlite3_step()を何度も呼び出すことでその結果が得られます。

 sqlite3_step()は結果の個数だけSQLITE_ROW、そして最後にSQLITE_DONEを返します。結果の取得は、

  • const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
  • double sqlite3_column_double(sqlite3_stmt*, int iCol);
  • int sqlite3_column_int(sqlite3_stmt*, int iCol);
  • sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
  • const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);

 にステートメント・ハンドルとカラム位置(0起点)を与えることで得られます。

九九の表から五の段を検索する
sqlite3_stmt* statement;
const char* command = "SELECT * FROM mul_table WHERE x = 5;"
sqlite3_prepare_v2(db, command, -1, &statement, 0);
while ( sqlite3_step(statement) == SQLITE_ROW ) {
  int x = sqlite3_column_int(statement,0);
  int y = sqlite3_column_int(statement,1);
  int z = sqlite3_column_int(statement,2);
  cout << x << '*' << y << '=' << z << endl; 
}

Unicodeの扱い

 SQLiteで扱う文字はUTF-8もしくはUTF-16となっており、ここまでの説明はUTF-8のものです。文字コードをUTF-16とする関数にはsqlite3_column_text16()のように末尾に16がつけられています。このとき、文字列を表す型はchar*ではなくvoid* です。wchar_t*ではないことに注意してください(SQLiteはwchar_t型をサポートしない処理系を考慮してvoid*を使っているのでしょう)。

 まとめとして、SQLiteの主要APIを使ったUTF-16(Unicode)版サンプルコードを示します。

Unicode版サンプルコード
/*
 * SQLite のC++によるサンプル(Visual C++)
 *  cl -MD -EHsc -I. trial.cpp sqlite3.lib
 */
 
#include <iostream>  // wcout, endl
#include <string>    // wstring
#include <locale>    // locale
#include <sqlite3.h> // SQLite3

struct Record {
  wchar_t* shop;
  wchar_t* dish;
  int      price;
  double   score;
};

using namespace std;

typedef const wchar_t* cwp;

int main() {

  /*
   * Unicode出力のためのlocale設定
   */
  wcout.imbue(locale("japanese"));

  sqlite3* db;
  int result;

  /*
   * データベースのオープン 
   */
  sqlite3_open16(L"trial.db", &db);

  sqlite3_stmt* statement;
  const void* command;

  /*
   * シングル・ステートメント SQL の実行
   */
  command = L"DROP TABLE IF EXISTS 飯屋";
  sqlite3_prepare16_v2(db, command, -1, &statement, 0);
  sqlite3_step(statement);
  sqlite3_finalize(statement);

  command = L"CREATE TABLE 飯屋 ( 店名 TEXT, 品名 TEXT, 価格 INTEGER, 評価 FLOAT);";
  sqlite3_prepare16_v2(db, command, -1, &statement, 0);
  sqlite3_step(statement);
  sqlite3_finalize(statement);

  /*
   * マルチ・ステートメント SQL の実行
   */
  command = L"INSERT INTO 飯屋 VALUES ( '蓬莱', 'ラーメン', 500, 2.5 );"
            L"INSERT INTO 飯屋 VALUES ( '崑崙', 'ラーメン', 550, 3.0 )";
  while ( *static_cast<cwp>(command) ) {
    sqlite3_prepare16_v2(db, command, -1, &statement, &command);
    result = sqlite3_step(statement);
    sqlite3_finalize(statement);
  }

  /*
   * パラメータのバインド
   */
  Record data[] = {
    { L"来来軒",   L"ラーメン",   600, 3.0 },
    { L"来来軒",   L"チャーハン", 500, 4.5 },
    { L"来来軒",   L"ニラレバ",   650, 2.0 },
    { L"激旨食堂", L"チャーハン", 500, 4.8 },
    { L"激旨食堂", L"ギョーザ",   350, 3.5 },
    { 0 }
  };

  command = L"INSERT INTO 飯屋 VALUES ( ?, ?, ?, ? )";
  sqlite3_prepare16_v2(db, command, -1, &statement, 0);
  for ( Record* rec = data; rec->shop; ++rec ) {
    sqlite3_reset(statement);
    sqlite3_bind_text16(statement, 1, rec->shop , -1, SQLITE_STATIC);
    sqlite3_bind_text16(statement, 2, rec->dish , -1, SQLITE_STATIC);
    sqlite3_bind_int   (statement, 3, rec->price);
    sqlite3_bind_double(statement, 4, rec->score);
    result = sqlite3_step(statement);
  }
  sqlite3_finalize(statement);

  /*
   * クエリの実行と値の取得
   */
  command = L"SELECT * FROM 飯屋 WHERE 評価 >= 3.0";
  sqlite3_prepare16_v2(db, command, -1, &statement, 0);
  while ( sqlite3_step(statement) == SQLITE_ROW ) {
    wcout << static_cast<cwp>(sqlite3_column_text16(statement,0)) 
          << " | "
          << static_cast<cwp>(sqlite3_column_text16(statement,1)) 
          << " | "
          << sqlite3_column_int   (statement,2) << " | "
          << sqlite3_column_double(statement,3)
          << endl;
  }

  /*
   * データベースのクローズ
   */
  sqlite3_close(db);

}

次のページ
"おこづかいちょう"のからくり

この記事は参考になりましたか?

特集記事連載記事一覧

もっと読む

この記事の著者

επιστημη(エピステーメー)

C++に首まで浸かったプログラマ。Microsoft MVP, Visual C++ (2004.01~2018.06) "だった"りわんくま同盟でたまにセッションスピーカやったり中国茶淹れてにわか茶...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/2414 2008/05/22 09:04

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー