¿Preguntas con declaraciones preparadas en Android?
En Android, android.database.sqlite.SQLiteStatement
me permite usar declaraciones preparadas en SQLite para evitar ataques de inyección. Su método de execute
es adecuado para crear / actualizar / eliminar operaciones, pero no parece haber ningún método para las consultas que devuelve un cursor o similar.
Ahora en iOS puedo crear declaraciones preparadas de tipo sqlite3_stmt*
y usarlas para consultas, así que sé que esto no es una limitación de SQLite. ¿Cómo puedo realizar consultas con declaraciones preparadas en Android?
- Problemas para obtener Calendar.WEEK_OF_YEAR
- SQLiteException: cerca de "": error de sintaxis (código 1) al compilar
- Cómo convertir MDB a SQLite en Android
- Recuperar un nombre de usuario y una contraseña en SQLITE DB por EMAIL_ADDRESS en ANDROID
- Android - ¿Se puede utilizar el Cursor SQLite después de cerrar la base de datos?
- Datos dinámicamente de datos de tabla de Android
- Sqlite en Android: Cómo crear una función sqlite dist db - que se utilizará en la aplicación para calcular la distancia utilizando lat, largo
- Unir 3 tablas en la base de datos SQLite
- Cómo utilizar la cláusula LIKE en la función de consulta
- Base de datos SQLite de Android compartida entre actividades
- Crear la función definida por el usuario en sqlite android?
- Eliminar la base de datos sqlite al actualizar la nueva versión de la aplicación
- Android OrmLite base de datos pre-poblar
Una declaración preparada le permite hacer dos cosas
- Acelerar el rendimiento ya que la base de datos no necesita analizar la sentencia cada vez
- Bind & escape en la sentencia para que se salve contra ataques de inyección
No sé exactamente donde / cuando la implementación de SQLite de Androids realmente usa sqlite3_prepare
(afiak no sqlite3_prepare_v2
– vea aquí ) pero lo usa de otra manera que no pudo obtener Alcanzó el tamaño MAX para errores de caché de compilación-sql .
Así que si quieres consultar la base de datos tienes que depender de la implementación no hay forma de saberlo para hacerlo con SQLiteStatement
.
En cuanto a la seguridad de inyección, cada consulta de base de datos, insertar, etc método tiene versiones (a veces alternativas) que le permiten enlazar los argumentos.
Por ejemplo, si desea obtener un Cursor
de
SELECT * FROM table WHERE column1='value1' OR column2='value2'
Cursor SQLiteDatabase#rawQuery(
-
String sql
,:SELECT
completo que puede incluir?
en todos lados -
String[] selectionArgs
: lista de valores que reemplazan?
, Para que aparezcan
)
Cursor c1 = db.rawQuery( "SELECT * FROM table WHERE column1=? OR column2=?", new String[] {"value1", "value2"} );
Cursor SQLiteDatabase#query (
-
String table
nombre de tabla, puede incluirJOIN
etc -
String[] columns
,: lista de las columnas necesarias,null
=*
-
String selection
,:WHERE
cláusula withouth ¿WHERE
puede / debe incluir?
-
String[] selectionArgs
,: lista de valores que reemplazan?
, Para que aparezcan -
String groupBy
CláusulaGROUP BY
sinGROUP BY
-
String having
:HAVING
cláusula w / oHAVING
-
String orderBy
:String orderBy
ORDER BY
sinORDER BY
)
Cursor c2 = db.query("table", null, "column1=? OR column2=?", new String[] {"value1", "value2"}, null, null, null);
Vía ContentProviders – ese caso es ligeramente diferente ya que interactúa con un proveedor abstracto, no una base de datos. No hay ninguna garantía de que hay una base de datos sqlite que respalda el ContentProvider
. Tan a menos que usted sepa qué columnas hay / cómo el abastecedor trabaja internamente usted debe pegarse a lo que la documentación dice.
Cursor ContentResolver#query(
-
Uri uri
URI que representa la fuente de datos (traducido internamente a una tabla) -
String[] projection
lista de las columnas requeridas,null
=*
-
String selection
,:WHERE
cláusula withouth ¿WHERE
puede / debe incluir?
-
String[] selectionArgs
,: lista de valores que reemplazan?
, Para que aparezcan -
String sortOrder
:String sortOrder
ORDER BY
sinORDER BY
)
Cursor c3 = getContentResolver().query( Uri.parse("content://provider/table"), null, "column=? OR column2=?", new String[] {"value1", "value2"}, null);
Sugerencia: si desea LIMIT
aquí, puede agregarlo a la cláusula ORDER BY
:
String sortOrder = "somecolumn LIMIT 5";
O dependiendo de la implementación del ContentProvider
agrega como un parámetro al 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");
En todos los casos ?
Será reemplazado por la versión de escape de lo que se pone en el argumento de enlace.
?
+ "hack'me"
= 'hack''me'
- No se puede conectar al servicio de cámara
- Widget onUpdate llamado cuando se inicia la Actividad de configuración