AndroidでのSQL文発行でLIKE演算子を使う時のはまりポイント

Androidアプリ内でSQL文を発行する場合、LIKE演算子の使い方によっては例外が発生してしまいます。

例えばメモ帳アプリの場合。「notes」というテーブルに、メモのタイトルを表す「title」列と、本文を表す「body」列が定義されているとします。

ここで、中間一致検索として本文(body)に「qqq」という文字列が格納されているデータを検索したい場合、コンソールからSQL文を発行するときは下記のように書きます。

SELECT title, body FROM notes WHERE body LIKE '%qqq%';

これと同様なことをAndroidでquery実行する場合、「%」とプレースホルダの「?」の扱いに若干注意が必要です。
例えば以下のように書くと例外が発生します。

// 誤った書き方
String sql= "SELECT title, body FROM notes WHERE body LIKE '%?%'";
String searchWord= "qqq";
Cursor cursor = db.rawQuery(sql, new String[] { searchWord });

正常に動作させるためには、一例としてSQLiteの文字列連結演算子「||」とエスケープ文字を使って以下のように書く必要があります。

// 正常動作する書き方
String sql= "SELECT title, body FROM notes WHERE body LIKE '%' || ? || '%' ESCAPE '$'";
String searchWord = "qqq";
Cursor cursor = db.rawQuery(sql, new String[] { searchWord });

上記の「ESCAPE '$'」は、エスケープ文字の指定で、ここでは「$」を指定しています。SQLiteにおいて「%」や「_」は、パターンマッチングの演算子として使われるため、それらの文字そのものを検索ワードにしたい場合には、エスケープ文字を直前に付加する必要があります。例えば上記コードの例でいえば、「qqq」ではなく「降水確率50%」という文字列を検索したい場合は、searchWordの定義箇所を次のように書きます。

String searchWord = "降水確率50$%"; //「50%」ではなく「50$%」にする

以上、以前にメモ帳アプリを作った時にハマったポイントです。いつか不意に忘れてしまいそうなので、ここに書き留めておきます。