初期データの投入方法

いやお久しぶりです。

データの管理にSQLiteを使うとして、初期データを作るのに、数テーブル、数件程度のデータであれば
SQLiteOpenHelperのonCreate内に直接SQLを書いてやれば良いですが、
数百件にもなるとそうも言ってられなくなります。

方法としては、SQLiteファイルを予め用意しておき、直接コピーして使う方法がありますが、
参考:http://y-anz-m.blogspot.com/2011/01/android-sqline-database.html


SQLiteからdumpしたデータを流し込む方法を紹介したいと思います。
前提条件として、予め必要なデータの入ったSQLiteデータベースは用意されているとします。
こんな感じの、「test.sqlite」を用意しておきました。

sqlite> .schema
CREATE TABLE test_table( _id integer primary key, name text, total int);
sqlite> select * from test_table;
1|hogehoge|100
2|fugafuga|200
3|foo|300
4|bar|400

こいつをdumpしてsqlファイルにします。dumpの方法はMac、Linuxでsqlite3コマンドを使うなら

> sqlite3 test.sqlite .dump > dump.sql

これでdump.sqlが出来ます。中身は

> cat dump.sql 
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE test_table( _id integer primary key, name text, total int);
INSERT INTO "test_table" VALUES(1,'hogehoge',100);
INSERT INTO "test_table" VALUES(2,'fugafuga',200);
INSERT INTO "test_table" VALUES(3,'foo',300);
INSERT INTO "test_table" VALUES(4,'bar',400);
COMMIT;

こうなってました。
このファイルから必要無い行を削除して、Androidプロジェクトのassetsディレクトリに保存します。
必要な行だけというのは場合にもよりますが、SQLiteOpenHelperのonCreateでデータを作成する場合、
onCreate自体がトランザクション内部で行われるため、dumpファイルからトランザクションに関係する部分を消す必要があります。

CREATE TABLE test_table( _id integer primary key, name text, total int);
INSERT INTO "test_table" VALUES(1,'hogehoge',100);
INSERT INTO "test_table" VALUES(2,'fugafuga',200);
INSERT INTO "test_table" VALUES(3,'foo',300);
INSERT INTO "test_table" VALUES(4,'bar',400);

このファイルを「dump.sql」で保存して、assets直下に保存したとします。

SQLiteOpenHelperのonCreate()をこんな感じで実装しました。

@Override
public void onCreate(SQLiteDatabase db) {
    InputStream is;
    BufferedReader bfReader;
        try {
            is = mContext.getAssets().open("dump.sql");
            bfReader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line;
            while(( line = reader.readLine() ) != null){
                if(! line.equals("") ){
                    line.append(str);
                    line.append("\n");
                }
            }
            sb.deleteCharAt(sb.length()-1);
            for(String sql: sb.toString().split(";")){
                db.execSQL(sql);
            }
        } catch (IOException e) {
             e.printStackTrace();
    }
}

全部読み込んで、「;」で分割して1文ずつexecSQLをかけてやります。
データ中に改行が含まれている場合も上手く登録出来るように考慮したつもりですが、
データ中に「;」が現れたらどうするの?とか、細かい部分はよしなに考える必要があるかと。