AndroidでSQLiteを使用する
データ定義
AndroidでSQLLiteを扱うにはSQLiteDatabase
クラスを使用します。
このSQLiteDatabase
のインスタンス生成を簡略化してくれるのがSQLiteOpenHelper
です。
SQLiteOpenHelper
は抽象クラスであり、DBオープン時、テーブルのバージョンアップ時の実装を追加することができます。
public class MySQLiteOpenHelper extends SQLiteOpenHelper { public MySQLiteOpenHelper(Context context) { // 任意のデータベースファイル名と、バージョンを指定する super(context, "pastingcontroller.db", null, 1); } /** * このデータベースを初めて使用する時に実行される処理 * @param db */ @Override public void onCreate(SQLiteDatabase db) { // テーブルの作成、初期データの投入等を行う。 } /** * アプリケーションの更新などによって、データベースのバージョンが上がった場合に実行される処理 */ @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // データの退避、テーブルの再構成等を行う。 } }
コンストラクタで任意の名称のデータベースを作成します。
onCreate
はこのヘルパクラスのインスタンスを使ってデータベースをオープンする際、コンストラクタで指定されたデータベースが無かった場合に実行されるメソッドです。
テーブルの作成や初期データの投入等を行います。
onUpgrade
はこのヘルパクラスのインスタンスを使ってデータベースをオープンする際、バージョンがあがっていた場合に実行されるメソッドです。(ここで言うバージョンはコンストラクタの第四引数のことです。)
テーブルの更新や、それに伴うデータの退避・再投入を行います。
たとえば、onCreate
でテーブルを作成する場合、以下のような実装になります。
@Override public void onCreate(SQLiteDatabase db) { db.execSQL( "create table sample_table (" + "_id integer primary key autoincrement not null, " + "text_column text not null, " + "num_column integer not null)" ); }
データ制御
データ操作を行うために、SQLiteDatabase
クラスのインスタンスを生成します。
作成したSQLiteOpenHelper
の実装を用いて以下のようにインスタンスを生成します。
SQLiteOpenHelper sqliteOpenHelper = new MySQLiteOpenHelper(getApplicationContext()); SQLiteDatabase db = sqliteOpenHelper.getWritableDatabase(); try { // データ操作 } finally { db.close(); }
getWritableDatabase
は読み書き両用のインスタンスを生成するのに用います。
読み取り専用のインスタンスが必要な場合はgetReadableDatabase
を使用します。
トランザクション
SQLiteでも意図的に記述することでトランザクション制御が可能です。
ループで大量のInsert等を投げる場合はトランザクション制御を行ったほうが処理が早くなるようです。
参考:SQLiteでINSERTが激しく遅い件
// トランザクション開始 db.beginTransaction(); try { /** Insert等のDB操作 */ db.setTransactionSuccessful(); } catch(Exception e) { e.printStackTrace(); } finally { // トランザクション終了 db.endTransaction(); }
beginTransaction
でトランザクションを開始し、endTransaction
でトランザクションを終了します。
トランザクション終了前にsetTransactionSuccessful
が呼ばれていればcommitされ、世ベレ帝無ければrollbackされます。なので、処理に成功した後は必ずsetTransactionSuccessful
を呼ぶ必要があります。
データ操作
登録
テーブルへのデータの登録(insert)は以下のように行います。
ContentValues values = new ContentValues(); values.put("text_column", "text"); values.put("num_column", 111); try { db.insert("sample_table", null, values); } finally { db.close(); }
登録に用いるデータははContentValues
オブジェクトに格納します。
insert
の第一引数にテーブル名、第三引数に登録したいデータを渡します。
第二引数は少々複雑です。
全ての項目がnull許可のテーブルに対して、空のContentValues
オブジェクトを渡した場合、発行されるSQLは以下のようになると思われます。
INSERT INTO foo;
しかし、SQLiteでは以下のように最低でも1つのカラム名を明記しなければ登録することができません。
INSERT INTO foo (somecol) VALUES (NULL);
上記の仕様を満たすために、第二引数には第三引数が空のオブジェクトだった場合にinsert文に加えるカラム名を渡すことになります。
参考:Insert method of SQLiteDatabase
更新
データの更新(update)は以下のように行います。
ContentValues values = new ContentValues(); values.put("num_column", 222); String whereClause = "text_column = ?"; String whereArgs[] = new String[1]; whereArgs[0] = "text"; try { db.update("sample_table", values, whereClause, whereArgs); } finally { db.close(); }
第一引数がテーブル名、第二引数が更新対象のContentValues
オブジェクト、第三引数がwhere句に指定する条件、第四引数が条件の"?"にバインドする値になります。
第四引数のwhereArgs
は文字列の配列です。数値型を条件にしたい場合は
String whereClause = "num_column = 111";
みたいな感じで直接条件文に記述することになります。
参考: Androidが再生産しているSQLインジェクション?
削除
データの削除(delete)は以下のようになります。
String whereClause = "text_column = ?"; String whereArgs[] = new String[1]; whereArgs[0] = "text"; try { db.delete("sample_table", whereClause, whereArgs); } finally { db.close(); }
読み取り
データの読み取り(select)は以下のようになります。
String[] columns = {"text_column ", "num_column"}; String selection = "text_column = ?"; String[] selectionArgs = {"text"}; String groupBy = null; String having = null; String orderBy = null; try { Cursor cursor = db.query("sample_table", columns, selection, selectionArgs, groupBy, having, orderBy); StringBuilder text = new StringBuilder(); while (cursor.moveToNext()){ String textColumn = cursor.getString(0); int numColumn = cursor.getInt(1); } } finally { db.close(); }
第一引数にテーブル名、第二引数に検索対象のカラム名(nullを指定すると全てが対象になります)、第三引数に検索条件、第四引数に検索条件へのバインド値を指定します。
必要に応じてgroup by句、having句、order by句を指定します。