在Android中,android.database.sqlite.SQLiteStatement
允許我在SQLite中使用預準備語句來避免注入攻擊。它的execute
方法適用於創建/更新/刪除操作,但是對於返回遊標等的查詢似乎沒有任何方法。查詢與Android中的準備語句?
現在在iOS中,我可以創建類型爲sqlite3_stmt*
的預準備語句並將它們用於查詢,所以我知道這不是SQLite的限制。我如何使用Android中的預準備語句執行查詢?
在Android中,android.database.sqlite.SQLiteStatement
允許我在SQLite中使用預準備語句來避免注入攻擊。它的execute
方法適用於創建/更新/刪除操作,但是對於返回遊標等的查詢似乎沒有任何方法。查詢與Android中的準備語句?
現在在iOS中,我可以創建類型爲sqlite3_stmt*
的預準備語句並將它們用於查詢,所以我知道這不是SQLite的限制。我如何使用Android中的預準備語句執行查詢?
準備好的語句可以做兩件事情
我不知道確切位置/時,機器人會SQLite的實現實際上使用sqlite3_prepare
(afiak不sqlite3_prepare_v2
- 見here),但我噸使用它,否則你不能得到Reached MAX size for compiled-sql statement cache errors。
所以,如果你想查詢數據庫,你必須依賴於實現,我不知道用SQLiteStatement
做到這一點。
關於注射安全性,每個數據庫查詢,插入等方法都有(有時候是可選的)版本,允許您綁定參數。
E.g.如果你想獲得一個Cursor
出
SELECT * FROM table WHERE column1='value1' OR column2='value2'
Cursor SQLiteDatabase#rawQuery(
String sql
,:全SELECT
statment可以包括?
到處String[] selectionArgs
:即取代?
值列表,在他們出現的順序)
Cursor c1 = db.rawQuery(
"SELECT * FROM table WHERE column1=? OR column2=?",
new String[] {"value1", "value2"}
);
Cursor SQLiteDatabase#query (
String table
,:表名,可以包括JOIN
等String[] columns
,:所需的列的列表中,null
= *
String selection
,:WHERE
條款withouth的WHERE
可/應包括?
String[] selectionArgs
,:GROUP BY
條款W/O GROUP BY
String having
,:HAVING
條款,替換?
,爲了值出現String groupBy
,名單W/O HAVING
String orderBy
:ORDER BY
子句的w/o ORDER BY
)
Cursor c2 = db.query("table", null,
"column1=? OR column2=?",
new String[] {"value1", "value2"},
null, null, null);
通過ContentProviders - 因爲你有一個抽象的提供商,而不是一個數據庫進行交互這種情況下略有不同。我們不保證有一個支持ContentProvider
的sqlite數據庫。所以,除非你知道哪些列/哪些提供者在內部工作,你應該堅持文檔所說的。
Cursor ContentResolver#query(
Uri uri
,:一個URI表示該數據源(內部轉換到一個表)String[] projection
,:所需的列的列表中,null
= *
String selection
,:WHERE
子句withouth WHERE
can/should include ?
String[] selectionArgs
,:ORDER BY
條款W/O ORDER BY
)
Cursor c3 = getContentResolver().query(
Uri.parse("content://provider/table"), null,
"column=? OR column2=?",
new String[] {"value1", "value2"},
null);
提示:該更換?
,以便它們出現
String sortOrder
值的列表,如果你想LIMIT
在這裏你可以添加它的ORDER BY
條款: String sortOrder = "somecolumn LIMIT 5";
或取決於ContentProvider
執行添加它作爲參數傳遞給Uri
:
Uri.parse("content://provider/table?limit=5");
// or better via buildUpon()
Uri audio = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
audio.buildUpon().appendQueryParameter("limit", "5");
在所有情況下?
將通過你把在綁定參數中的轉義版本所取代。
?
+ "hack'me"
= 'hack''me'
優秀帖子,謝謝你,幫了我很多。像這樣的時代讓我覺得我們需要能夠不止一次地改裝。 – Louis 2012-07-03 07:11:18
即使這個答案很安靜,是否有一種解決方法來綁定除String以外的其他任何東西。我的查詢請求一個數值被綁定,但SqliteDatabase中的每個方法都使用一個String數組。如果我自己創建PreparedStatement,我可以執行查詢來恢復光標......我不相信沒有解決方案,但我一直沒有找到它。 – AxelH 2015-08-25 07:06:18
@AxelH解決方法是,所有東西都可以用字符串表示。例如使用'String.valueOf(yourNumericThingHere)'。 – zapl 2015-08-25 07:27:41