在Android中使用预准备语句查询?

时间:2012-03-25 00:59:58

标签: android sql sqlite prepared-statement

在Android中,android.database.sqlite.SQLiteStatement允许我在SQLite中使用预准备语句来避免注入攻击。它的execute方法适用于创建/更新/删除操作,但似乎没有任何方法可用于返回游标等的查询。

现在在iOS中我可以创建类型为sqlite3_stmt*的预准备语句并将它们用于查询,所以我知道这不是SQLite的限制。如何在Android中使用预准备语句执行查询?

1 个答案:

答案 0 :(得分:40)

准备好的声明允许你做两件事

  • 加速性能,因为数据库每次都不需要解析语句
  • bind&声明中的转义参数,以防止注入攻击

我不确切知道Androids SQLite实现在何处/何时实际使用sqlite3_prepare(afiak not sqlite3_prepare_v2 - 请参阅here)但它确实使用了它,否则你无法获得SQLiteStatement 3}}

因此,如果您想查询数据库,您必须依赖于实现,我无法通过Cursor进行查询。

关于注入安全性,每个数据库查询,插入等方法都有(有时是替代)版本,允许您绑定参数。

E.g。如果你想从

中获得SELECT * FROM table WHERE column1='value1' OR column2='value2'
Cursor SQLiteDatabase#rawQuery(

String sql

  • SELECT,:完整的?声明,其中包含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
  • WHEREWHERE子句无?可以/应该包含String[] selectionArgs
  • ?,:替换String groupBy的值列表,按其显示
  • GROUP BYGROUP BY条款没有String having
  • HAVINGHAVING条款没有String orderBy
  • ORDER BYORDER BY条款没有)

Cursor c2 = db.query("table", null, "column1=? OR column2=?", new String[] {"value1", "value2"}, null, null, null);

ContentProvider

通过ContentProviders - 由于您与抽象提供者而不是数据库进行交互,因此情况略有不同。实际上并不能保证有一个sqlite数据库支持Cursor ContentResolver#query(。因此,除非您知道哪些列/提供者如何在内部工作,否则您应该坚持文档所说的内容。

Uri uri

  • String[] projection,:表示数据源的URI(内部转换为表格)
  • null,:所需列的列表,* = String selection
  • WHEREWHERE子句无?可以/应该包含String[] selectionArgs
  • ?,:替换String sortOrder的值列表,按其显示
  • ORDER BYORDER BY条款没有)

Cursor c3 = getContentResolver().query( Uri.parse("content://provider/table"), null, "column=? OR column2=?", new String[] {"value1", "value2"}, null);

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");

?

在所有情况下,?都将替换为您在bind参数中放置的转义版本。

"hack'me" + 'hack''me' = {{1}}