Tips

SQLiteDatabaseクラスを使いSQLを実行する(query) 【Android TIPS】

1
データベースその2
SQLiteDatabaseクラスを使い
SQLを実行する(query)
SQLiteDatabaseクラスを使い、SELECT文を実行する方法を紹介します。
SELECT文はデータベースからレコードを抽出する時に使用するSQL命令文です。
query()、rawQuery()、queryWithFactory()、rawQueryWithFactory()という4つのメソッドがあり、全てに共通している点は戻り値のデータ型がCursorクラスということです。この戻り値がSELECT文を実行した結果として取得したレコード群を表すことになります。
query()メソッド
SQLiteDatabaseオブジェクトで、レコードを検索するにはquery()、もしくはrawQuery()を使用する方法がもっともポピュラーです。まずはquery()から見ていきましょう。このメソッドはオーバーロードされており、以下の3つのシグネチャが存在します。

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;

rawQuery()メソッド
次にrawQuery()です。このメソッドはStringとして定義したSQL文をそのまま実行することができます。

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クラスはデータベースへの問い合わせ結果をラッピングしたクラスで、このオブジェクトを操作することで、行や列を読み込むことができます。
コンテントプロバイダで紹介した方法と同様に使用することができます。

queryWithFactory()メソッドとrawQueryWithFactory()メソッド
SELECT文を実行する方法には、queryWithFactory()やrawQueryWithFactory()を使用する方法もあります。その名の通り、Factory(ここではCursorFactoryのことを指します)を指定して実行したいときに使うメソッドです。
これらのメソッドはそれぞれ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()に集約されていることが分かりました。
選択肢が多いので迷ってしまいがちですが、どれを使ったとしても終着点は同じということですね。

Androidアプリ開発の必須知識!JAVAプログラミングを学べる連載リンク

はじめてのJAVA 連載

Recent News

Recent Tips

Tag Search