【c++】SQLiteの導入と基本的な操作

c++

概要

「SQLiteをはじめたいけど、始め方が分からない…」

このブログでは、
・SQLiteのプロジェクト導入
・sqlの実行
をするところまで解説し、そんなお悩みに答えたいと思います。

サンプル

GitHub - daiki1003/cocos_sqlite_sample: This is a sample project for using sqlite on cocos2d-x project.
This is a sample project for using sqlite on cocos2d-x project. - daiki1003/cocos_sqlite_sample

SQLiteのプロジェクト導入

すごく簡単です。

1. sqliteのダウンロード
2. プロジェクトへの追加
3. コーディング

の3stepです。(だいたいそうか笑

sqliteのダウンロード

SQLite Download Page

よりダウンロードします。

今回はamalgamation (一番上のリンク)をダウンロードしました。執筆時点では3.8.8.3が最新です。
※amalgamationは混合とかって意味らしいです。

注意!
もしupdate文を打つ際にlimitもしくはorder byを使用する予定がある方はamalgamationではなく生のソースコードをダウンロードしてコンパイルして入れてください。

それに関してはこちらのエントリで。

【c++】sqliteのupdateはlimit出来ない
※ただし、自分でソースコードをビルドして入れたものは大丈夫だそうです。 1.0 The SQLite Amalgamation

また、生のソースからの入れ方については当記事では説明しておりません。

プロジェクトへの追加

以下3つのファイルを追加します。

・sqlite3.c
・sqlite3.h
・sqlite3ext.h

ここまでで導入は終わりです。簡単でしょう?

コーディング

では実際にソースを書いてみましょう。
最終系はこんな感じです。

string dbName = "test.db";
auto filePath = FileUtils::getInstance()->getWritablePath() + dbName;
    
auto status = sqlite3_open(filePath.c_str(), &db);
if(status != SQLITE_OK)
{
    CCLOG("error for opening db.");
}
else
{
    CCLOG("open successed!");
}
    
// create table
auto create_table = "create table user (id integer, age integer)";
status = sqlite3_exec(db, create_table, nullptr, nullptr, &errorMessage);
if(status != SQLITE_OK) CCLOG("create: %s", errorMessage);

// insert row
auto insert = "insert into user(id, age) values (1, 15)";
status = sqlite3_exec(db, insert, nullptr, nullptr, &errorMessage);
if(status != SQLITE_OK) CCLOG("insert: %s", errorMessage);

// update row
auto update = "update user set age = 20 where id = 1";
status = sqlite3_exec(db, update, nullptr, nullptr, &errorMessage);
if(status != SQLITE_OK) CCLOG("update: %s", errorMessage);

// select row(s)
auto select = "select * from user where id = 1";
status = sqlite3_exec(db, select, callback, nullptr, &errorMessage);
if(status != SQLITE_OK) CCLOG("select: %s", errorMessage);

sqlite3_close(db);

出力

cocos2d: open successed!
id = 1
age = 20

解説

上記のコードを読んで理解出来る人は多分解説はいらないと思います。

L1〜L2   DBの場所を用意
L4〜L12   databaseをopen
L14〜L17  userテーブルの作成
L19〜L22  userにデータをinsert
L24〜L27  userデータをupdate
L29〜31  userデータをselect
L34    最後は必ずdatabaseをclose

さて、selectのexecの第3引数だけcallbackが指定されています。
コールバックは以下の様になっています。

static int callback(void *_, int argc, char **argv, char **columnName){
    for(int i=0; i < argc; i++)
        printf("%s = %s\n", columnName[i], argv[i] ? argv[i] : "null");
    return SQLITE_OK;
}

第一引数:今回使っていませんが、呼び出し元のインスタンスが入っています。
第二引数:カラム数
第三引数:データの値の配列
第四引数:カラム名

callback以外にないのか?

さて、先ほどの書き方で少し問題が出てきます。
callback関数が別関数になってしまっているので処理が煩雑になりがちです。

もう一つの書き方を紹介します。

sqlite3_stmt* statement = nullptr;
auto select = "select * from user where id = 1";
if(sqlite3_prepare_v2(db, select, -1, &statement, nullptr) != SQLITE_OK) CCLOG("prepare: %s", errorMessage);
else
{
    if (sqlite3_step(statement) == SQLITE_ROW)
    {
        for (int i = 0; i < sqlite3_column_count(statement); i++)
        {
            string name = sqlite3_column_name(statement, i);
            int columnType = sqlite3_column_type(statement, i);
            if (columnType == SQLITE_INTEGER)
            {
                CCLOG("%s = %d", name.c_str(), sqlite3_column_int(statement, i));
                continue;
            }
        }
    }
}
sqlite3_reset(statement);
sqlite3_finalize(statement);

出力は先ほどと同じです。

L1   状態を表す変数statementを用意
L3   sqlをコンパイル
L6   sqlite3_stepでsqlを実行
L7   sqlite3_column_countでカラム数を取得
L10  sqlite3_column_nameでi番目のカラム名を取得
L11  sqlite3_column_typeでカラムのタイプ(int, char...)を取得
L12  sqlite3_column_*で各タイプの値の取得

このような形になります。

誰かのお役に立てば。

【cocos2d-x】cocos記事一覧
cocos記事一覧 Pimpl 激震が走った、Pimplイディオム enum enum struct(class)とは cast 決定版!*_castまとめ sqlit...

コメント

タイトルとURLをコピーしました