SELECT文はデータベースからレコードを抽出する時に使用するSQL命令文です。
query()、rawQuery()、queryWithFactory()、rawQueryWithFactory()という4つのメソッドがあり、全てに共通している点は戻り値のデータ型がCursorクラスということです。この戻り値がSELECT文を実行した結果として取得したレコード群を表すことになります。
public Cursor query (String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
public Cursor query (String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having, String orderBy)
public Cursor query (boolean distinct, String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
引数が多いのですが、3番目のquery()が最も多い引数を持ち、1番目や2番目はいくつかの引数が省略されているだけにすぎません。下表は3番目のquery()の引数を全て抜き出したものです。
| データ型 | 引数名 | 概要 |
|---|---|---|
| boolean | distinct | 検索結果から重複データを削除するかどうか |
| String | table | テーブル名 |
| String[] | columns | 検索結果に含める列名(nullの場合は全ての列) |
| String | selection | 検索条件 |
| String[] | selectionArgs | selectionのパラメータ「?」に置き換わる値 |
| String | groupBy | SQLのGROUPBY句 |
| String | having | SQLのHAVING句 |
| String | orderBy | SQLのORDERBY句 |
| String | limit | 検索結果レコード数の上限 |
SQLのSELECT文に用いられる句と引数が対応していることが分かります。
使用例は以下の通り。dbはSQLiteDatabaseオブジェクトです。
Cursor c = db.query("person", new String[] { "name", "age" }, "age >= ?",
new String[]{"25"}, null, null, null);
この例では2番目のquery()を使用しています。この実行結果は以下のSQLと同義になります。
SELECT name, age FROM persion WHERE age >=25;
public Cursor rawQuery (String sql, String[] selectionArgs)
先ほどと同じように引数を全て抜き出してみましょう。
| データ型 | 引数名 | 概要 |
|---|---|---|
| String | sql | SQL文 |
| String[] | selectionArgs | SQLのパラメータ「?」に置き換わる値 |
使用例は以下の通り。dbはSQLiteDatabaseオブジェクトです。
Cursor c = db.rawQuery("SELECT name, age FROM person WHERE age >= ?;", new String[]{"25"});
戻り値のCursorクラスはデータベースへの問い合わせ結果をラッピングしたクラスで、このオブジェクトを操作することで、行や列を読み込むことができます。
コンテントプロバイダで紹介した方法と同様に使用することができます。
これらのメソッドはそれぞれ2つずつオーバーロードがおこなれていますが、ここではその一部を紹介します。
まずは、queryWithFactory()とquery()のAndroidソースコードをのぞいてみましょう。
public Cursor query(boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit) {
return queryWithFactory(null, distinct, table, columns, selection, selectionArgs,
groupBy, having, orderBy, limit, null);
}
public Cursor queryWithFactory(CursorFactory cursorFactory,
boolean distinct, String table, String[] columns,
String selection, String[] selectionArgs, String groupBy,
String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
acquireReference();
try {
String sql = SQLiteQueryBuilder.buildQueryString(
distinct, table, columns, selection, groupBy, having, orderBy, limit);
return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
findEditTable(table), cancellationSignal);
} finally {
releaseReference();
}
}
4行目でquery()からqueryWithFactory()の呼び出しを行っています。ここで注目して頂きたいのは、第1引数がnullとなっている点です。この第1引数がCursorFactoryです。
次に、16行目に注目して下さい。queryWithFactory()からrawQueryWithFactory()の呼び出しを行っていることが分かります。
すなわち、query()メソッドを実行するとqueryWithFactory()→rawQueryWithFactory()と順に呼び出されていることになります。(rawQueryWithFactory()については後述します。)
また、4行目で第1引数にnullを渡していますので、16行目のrawQueryWithFactory()呼び出しの際に、第1引数のCursorFactoryにはnullが渡されていることになります。
では次に、rawQueryWithFactory()とrawQuery()のAndroidソースコードです。
public Cursor rawQuery(String sql, String[] selectionArgs) {
return rawQueryWithFactory(null, sql, selectionArgs, null, null);
}
public Cursor rawQueryWithFactory(
CursorFactory cursorFactory, String sql, String[] selectionArgs,
String editTable, CancellationSignal cancellationSignal) {
acquireReference();
try {
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
cancellationSignal);
return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
selectionArgs);
} finally {
releaseReference();
}
}
2行目でrawQuery()からrawQueryWithFactory()の呼び出しを行っています。先ほどと同じように第1引数のCursorFactoryがnullとなっています。
rawQueryWithFactory()の処理である9から11行目は、実際にSQLの実行を行っていることがわかります。
11行目では第1引数のcursorFactoryがnullのときは、mCursorFactory(Androidソースコードでは頭文字が”m”となっている変数は、インスタンス変数となります)を利用しています。
実は、この変数にはSQLiteOpenHelperクラスのコンストラクタの第3引数に指定したオブジェクトが格納されており、このコンストラクタでもnullを指定していた場合はCursorクラスのオブジェクトが戻り値になるようコーディングされています。
カスタマイズした独自のCursorを使いたい場合は、nullとなっていたCursorFactoryに独自クラスのオブジェクトを渡せば戻り値のデータ型が変わるという寸法です。
ここまでにSELECT文を実行するためのメソッドとして4つのメソッドを紹介しましたが、最終的には全てrawQueryWithFactory()に集約されていることが分かりました。
選択肢が多いので迷ってしまいがちですが、どれを使ったとしても終着点は同じということですね。