Ответ 1
подготовленный оператор позволяет вам делать две вещи
- ускорить работу, поскольку база данных не нуждается в синтаксическом анализе оператора
- связывать и убирать аргументы в инструкции, чтобы вы спаслись от инъекционных атак.
Я точно не знаю, где/когда реализация SQLite на Androids фактически использует sqlite3_prepare
(afiak not sqlite3_prepare_v2
- см. здесь) но он использует его, иначе вы не смогли бы получить Достигнутый размер MAX для ошибок кэша операторов compiled-sql.
Поэтому, если вы хотите запросить базу данных, вы должны полагаться на реализацию, я не знаю, как это сделать с помощью SQLiteStatement
.
Что касается безопасности инъекций, каждый запрос на базу данных, insert и т.д. имеет (иногда альтернативные) версии, которые позволяют связывать аргументы.
например. если вы хотите получить Cursor
из
SELECT * FROM table WHERE column1='value1' OR column2='value2'
Cursor SQLiteDatabase#rawQuery(
-
String sql
,: fullSELECT
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
оговорка withouthWHERE
может/должна включать?
-
String[] selectionArgs
,: список значений, которые заменяют?
, чтобы они отображались -
String groupBy
,:GROUP BY
статья безGROUP BY
-
String having
,:HAVING
статья безHAVING
-
String orderBy
:ORDER BY
статья безORDER BY
)
Cursor c2 = db.query("table", null,
"column1=? OR column2=?",
new String[] {"value1", "value2"},
null, null, null);
Через ContentProviders - этот случай немного отличается, поскольку вы взаимодействуете с абстрактным провайдером, а не с базой данных. Невозможно гарантировать, что база данных sqlite поддерживает ContentProvider
. Поэтому, если вы не знаете, какие столбцы существуют/как работает поставщик, вы должны придерживаться того, что говорит документация.
Cursor ContentResolver#query(
-
Uri uri
,: URI, представляющий источник данных (внутренне переведенный в таблицу) -
String[] projection
,: список требуемых столбцов,null
=*
-
String selection
,:WHERE
оговорка withouthWHERE
может/должна включать?
-
String[] selectionArgs
,: список значений, которые заменяют?
, чтобы они отображались -
String sortOrder
:ORDER BY
статья w/oORDER 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'