SQLiteのSQLのパラメータ化できる箇所
SQLiteのSQLiteDatabase.rawQueryで、SQLのパラメタライズが、できる場所とできない場所がありまして、調査結果を記しておきます。
「単なる文字列置換」では無いようです(よくよく考えれば当たり前ですね)。

SQLiteDatabase.rawQuery
概要
単純にSQLをそのまま実行するメソッド。SQLのパラメタライズも可能です。
プロトタイプ
Cursor SQLiteDatabase.rawQuery(String sql, String[] paramValues);
引数
使い方例
ざっくり以下のような使い方です。
// android.database.
// Cursor
// sqlite.
// SQLiteOpenHelper
// SQLiteDatabase
SQLiteDatabase db = openHelper.getWritableDatabase();
Cursor cursor = db.rawQuery(
"SELECT id, description, amount, date"
+ "FROM t_wallet " /* v v */
+ "WHERE description like ? AND amount >= ?",
new String[] { "'ポテト%'", "100" });
while(cursor.moveToNext()) {
int id = cursor.getInt(0);
String description = cursor.getString(1);
int amount = cursor.getInt(2);
byte[] blobDate = cursor.getBlob(3);
// ・
// ・
// ・
}
WHERE句の条件にある?を置き換えています。
条件式などの値を置換できます。
しかし単に文字列置換をしているのではなさそうでして、
【できない】文字列リテラルの中身は置換されない
たとえば、description like ?の部分を、description like '%?'とはできません。
あくまでもシングルコーテーションで囲まれている部分は、文字列リテラルとして扱われるので、その中の?は置換されず、単に?で終わっているdescriptionを見つけてきます。ただ、第二引数の要素数が合わない場合は例外が投入されます。
【できる】式の一部の置換はOK
以下のように、式の一部は、置換できます。
rawQuery(
"SELECT id FROM t_wallet " +
"WHERE amount >= ? + 30", /* OK */
new String[] { "100" })`
※ これ、当初「できない」としていましたが、できました。別の要因で例外が出ていたのかも。すみません。
また、以下のように、単独の値でなくてもOKです。
rawQuery(
"SELECT id FROM t_wallet " +
"WHERE amount >= ? + 30", /* OK */
new String[] { "(80 + 20)" })`
ところが、次のは駄目でした。「構文エラー」になります。
rawQuery(
"SELECT id FROM t_wallet " +
"WHERE amount >= ? ) + 30", /* NG */
new String[] { "(80 + 20" })`
?を式として扱って、第1引数のSQL単独で構文エラーになるのは駄目っぽいですね。
【できる】カラム名もOKです
以下のようにSELECT句やWHERE句、ORDER BY句の、カラム名は置換可能でした。
db.rawQuery(
"SELECT ? FROM t_wallet " +
"WHERE ? <= ? ORDER BY ? DESC",/* OK */
new String[] { "description",
"amount", "100", "amount"})`
しかし、
【できない】FROM句のテーブル名はダメでした
予想に反して、テーブル名は置換できないようです。
rawQuery(
"SELECT description FROM ? " + /* NG */
"WHERE amount <= 100 " +
"ORDER BY amount",
new String[] {"t_wallet"})
そして、
【できない】ORDER BY の DESCもダメですね
これ、できても良い気がしましたが、しっかり例外が投入されました。
rawQuery(
"SELECT description FROM t_wallet " +
"WHERE amount <= 100 " +
"ORDER BY id ?", /* NG */
new String[] {"DESC"})`
まとめ
結果をまとめると、以下のようになりました。
置換可能
- カラム名
- 値
置換できない
カラム名も構文的には式ですから、?は式を置換できるということで良いのかな。
