insert()メソッド
SQLiteDatabaseオブジェクトで、行を挿入するにはinsert()を使用する方法がもっともポピュラーです。
insert()を使用するには、あらかじめContentValuesオブジェクトに挿入するデータをセットしておく必要があります。
ContentValuesクラスは挿入するカラム名と値をマッピングしたHashmapのようなものです。
insert()のシグネチャは以下の通り。
public long insert (String table, String nullColumnHack, ContentValues values)
第1引数はテーブル名です。
第2引数のnullColumnHackはデータを挿入する際にnull値が許可されていないカラムに代わりに利用される値を指定します。
第3引数がContentValueオブジェクトです。
また、戻り値は正常終了した場合はROWID、失敗した場合は-1となります。
使用例は以下の通り。dbはSQLiteDatabaseオブジェクトです。
ContentValues values = new ContentValues(); values.put("name","山田 太郎"); values.put("age",35); long id = db.insert("person", null, values);
ContentValuesクラスはnewでインスタンス化し、put()を使いカラム名と対応する値を登録していきます。
この例で実行しているinsert()メソッドは以下のSQLと同義になります。
INSERT INTO person (name, age) VALUES("山田 太郎", 35);
insertOrThrow()メソッド
insert()を使用する以外にもinsertOrThrow()というメソッドを使用することもできます。
シグネチャは以下の通り。
public long insertOrThrow(String table, String nullColumnHack, ContentValues values) throws SQLException
insert()と違っている点はメソッド名とSQLExceptionをスローするということですが、公式リファレンスを見ても違いがよくわかりません。
しかし、Androidソースコードをのぞいてみると一目瞭然です。
public long insert(String table, String nullColumnHack, ContentValues values) { try { return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); } catch (SQLException e) { Log.e(TAG, "Error inserting " + values, e); return -1; } } public long insertOrThrow(String table, String nullColumnHack, ContentValues values) throws SQLException { return insertWithOnConflict(table, nullColumnHack, values, CONFLICT_NONE); }
insert()の場合は、SQL実行時に発生した例外をキャッチし、-1を返すようになっています。つまり、呼び出し元での例外処理が不要となる半面、細かなエラー処理をできなくなってしまうようです。
一方、insertOrThrow()の場合は、ただ単にSQLを実行しているだけです。発生した例外は呼び出し元にそのままスルーされます。
SQLExceptionを継承するクラスはたくさんありますが、代表的なものとして以下のものがあります。
- SQLiteOutOfMemoryException
- SQLiteReadOnlyDatabaseException
- SQLiteTableLockedException
これらの例外が発生したときに一概に-1が返るinsert()では都合が悪い場合があるわけですね。
insertWithOnConflict()メソッド
最後に、insertWithOnConflict()です。
このメソッドはこれまでに紹介した、insert()やinsertOrThrow()の中から呼び出されるメソッドで、実際にSQL文の生成や実行を行っています。
シグネチャは以下の通り。
public long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm)
insert()と違っている点は第4引数のconflictAlgorithmが追加されているということです。
この引数はINSERT文を実行時にコンフリクト(衝突)が発生した際、どのように処理するかを指定するオプションです。
指定できるオプション(定数)は以下の6つです。
オプション(定数) | 概要 |
CONFLICT_ROLLBACK | トランザクションがロールバックされる |
CONFLICT_ABORT | 実行中のSQLが中断されるが、ロールバックはしない |
CONFLICT_FAIL | 実行中のSQLが失敗し、それ以前の変更処理は有効のままとなる |
CONFLICT_IGNORE | 実行中のSQLは中断され、エラーコードは返さずにそのまま処理を継続する |
CONFLICT_REPLACE | 制約に違反するデータは元データを上書きする。 |
CONFLICT_NONE | オプションなし |
参考までにAndroidソースコードの抜粋を紹介します。
public static final int CONFLICT_ROLLBACK = 1; public static final int CONFLICT_ABORT = 2; public static final int CONFLICT_FAIL = 3; public static final int CONFLICT_IGNORE = 4; public static final int CONFLICT_REPLACE = 5; public static final int CONFLICT_NONE = 0; private static final String[] CONFLICT_VALUES = new String[] {"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "}; public long insertWithOnConflict(String table, String nullColumnHack, ContentValues initialValues, int conflictAlgorithm) { acquireReference(); try { StringBuilder sql = new StringBuilder(); sql.append("INSERT"); sql.append(CONFLICT_VALUES[conflictAlgorithm]); sql.append(" INTO "); sql.append(table); // ... 省略 ... SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs); try { return statement.executeInsert(); } finally { statement.close(); } } finally { releaseReference(); } }
SQL文を生成と実行をしていることがわかります。