查询与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/OGROUP BY
-
String having
,:HAVING
条款,替换?
,为了值出现 -
String groupBy
,名单W/OHAVING
-
String orderBy
:ORDER BY
子句的w/oORDER 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
子句withouthWHERE
can/should include?
-
String[] selectionArgs
,:ORDER BY
条款W/OORDER 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