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"})`
まとめ
結果をまとめると、以下のようになりました。
置換可能
- カラム名
- 値
置換できない
カラム名も構文的には式ですから、?
は式を置換できるということで良いのかな。