Estoy intentando hacer la siguiente consulta SQL dentro de Android:
String names = "'name1', 'name2"; // in the code this is dynamically generated
String query = "SELECT * FROM table WHERE name IN (?)";
Cursor cursor = mDb.rawQuery(query, new String[]{names});
Sin embargo, Android no reemplaza el signo de interrogación con los valores correctos. Podría hacer lo siguiente, sin embargo, esto no protege contra la inyección de SQL:
String query = "SELECT * FROM table WHERE name IN (" + names + ")";
Cursor cursor = mDb.rawQuery(query, null);
¿Cómo puedo solucionar este problema y poder utilizar la cláusula IN?
makePlaceholders
podría reemplazarse porTextUtils.join(",", Collections.nCopies(len, "?"))
. Menos prolijo.Caused by: android.database.sqlite.SQLiteException: near ",": syntax error (code 1): , while compiling: SELECT url FROM tasks WHERE url=?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
Ejemplo corto, basado en la respuesta del usuario 166390:
fuente
Lamentablemente, no hay forma de hacerlo (obviamente,
'name1', 'name2'
no es un valor único y, por lo tanto, no se puede utilizar en una declaración preparada).Por lo tanto, tendrá que bajar la vista (por ejemplo, creando consultas muy específicas, no reutilizables como
WHERE name IN (?, ?, ?)
) o no usar procedimientos almacenados e intentar evitar las inyecciones de SQL con algunas otras técnicas ...fuente
Como se sugiere en la respuesta aceptada pero sin usar la función personalizada para generar '?' Separados por comas. Por favor verifique el código a continuación.
fuente
Puede usar
TextUtils.join(",", parameters)
para aprovechar los parámetros de enlace de sqlite, dondeparameters
hay una lista con"?"
marcadores de posición y la cadena de resultado es algo así como"?,?,..,?"
.Aquí hay un pequeño ejemplo:
fuente
En realidad, podría usar la forma nativa de consulta de Android en lugar de rawQuery:
fuente
Esto no es válido
Esto es válido
Usando ContentResolver
fuente
En Kotlin puedes usar joinToString
fuente
Utilizo la
Stream
API para esto:fuente