AndroidのSQLiteでサポートしているJOIN句(のあるSELECT文)についてです。
結論から言ってしまうと、
①SQLiteそのものが右外部結合と完全外部結合はサポートしておらず、
②標準APIのSQLiteDatabaseでは面倒くさいので、O/Rマッピングライブラリを使うといいですよ。
です。
アジェンダ
- そもそもSQLiteのJOINのサポートの可否
- SQLiteDatabase#rawQueryメソッドでJOIN句のあるSELECT実行
- 非サポートのJOIN句のあるSELECT実行時の例外
- SQLiteDatabase#rawQuery使いたくないなぁ
まず前提として、そもそもJOINのサポートの可否
Android Developersサイトの「Using Databases」の項の冒頭に、「Android provides full support for SQLite databases.」と記載があります。
Android Developers: Using Databases
SQLiteでは、「LEFT OUTER JOIN is implemented, but not RIGHT OUTER JOIN or FULL OUTER JOIN.」と記載があります。
SQLite:SQL Features That SQLite Does Not Implement
すなわち、各JOINの可否は以下のとおりです。
- サポート
- INNER JOIN(内部結合)
- LEFT OUTER JOIN(左外部結合)
- CROSS JOIN(交差結合)
- 非サポート
- RIGHT OUTER JOIN(右外部結合)
- FULL OUTER JOIN(完全外部結合)
JOIN句のあるSELECT文の実行
SQLiteDatabase#queryメソッドではJOIN句のあるSELECT文を実行することができません。
なので、rawQueryメソッドを用いることになります。
String sql = "SELECT * FROM foo INNER JOIN bar ON foo.a = bar.a";
Cursor cursor = database.rawQuery(sql, null);
if (cursor.moveToFirst()) {
do {
int foo_a = cursor.getInt(0);
String foo_b = cursor.getString(1);
int bar_a = cursor.getInt(2);
String bar_b = cursor.getString(3);
Log.v("内部結合", "" + foo_a + ":" + foo_b + ":" + bar_a + ":" + bar_b);
} while (cursor.moveToNext());
}
結合するフィールド名が同じであれば、USING句を使用するのも可です。
非サポートのJOIN句のあるSELECT文の実行
非サポートのJOIN句のあるSELECT文を実行すると、以下のように例外SQLiteExceptionがスローされます。
E/AndroidRuntime: java.lang.RuntimeException: Unable to resume activity {【パッケージ/実行クラス】: android.database.sqlite.SQLiteException:
RIGHT and FULL OUTER JOINs are not currently supported: , while compiling: SELECT * FROM foo FULL OUTER JOIN bar ON foo.a = bar.a
でも、SQLiteDatabase#rawQueryは使用を避けたい人もいる
SQLiteDatabase#rawQueryメソッドは、結局、SQL文を文字列で記述する羽目になるので、半角スペースやシングルコーテーションの書き忘れを頻繁にしてしまう人には、使用は回避できるものなら、回避したいですよね。
当「JOIN句について」の件だけでなく、SQLiteDatabase#queryメソッドを使用することですら、引数の多さに困惑している人もいると思います。
そこで、DBアクセスのライブラリを探してみますと、サードパーティ製のO/Rマッピング(Object Relational Mapping)ライブラリの一つであるOrmLiteの導入を検討してみてはいかがでしょうか?という提案になります。
OrmLiteには「@JoinColumn」というアノテーションがありますので。
最後に
では、OrmLiteの詳しい説明は…せずじまいでこの投稿は終わっちゃいますすすすみません。
要は、当記事は「JOINには気を付けろ!」という注意喚起をしたかったのでした。
以上です。