Próbuję wykonać następujące zapytanie SQL w systemie 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});
Jednak Android nie zastępuje znaku zapytania prawidłowymi wartościami. Mógłbym zrobić co następuje, jednak to nie chroni przed wstrzyknięciem SQL:
String query = "SELECT * FROM table WHERE name IN (" + names + ")";
Cursor cursor = mDb.rawQuery(query, null);
Jak mogę obejść ten problem i móc skorzystać z klauzuli IN?
makePlaceholders
można by zastąpićTextUtils.join(",", Collections.nCopies(len, "?"))
. Mniej gadatliwy.Caused by: android.database.sqlite.SQLiteException: near ",": syntax error (code 1): , while compiling: SELECT url FROM tasks WHERE url=?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
Krótki przykład na podstawie odpowiedzi użytkownika166390:
źródło
Niestety nie
'name1', 'name2'
da się tego zrobić (oczywiście nie jest to pojedyncza wartość i dlatego nie można jej użyć w przygotowanym zestawieniu).Będziesz więc musiał obniżyć swoje cele (np. Tworząc bardzo szczegółowe zapytania nienadające się do ponownego użycia, takie jak
WHERE name IN (?, ?, ?)
) lub nie używać procedur składowanych i próbować zapobiegać iniekcjom SQL za pomocą innych technik ...źródło
Jak sugeruje zaakceptowana odpowiedź, ale bez używania funkcji niestandardowej do generowania znaku „?” Oddzielonego przecinkami. Sprawdź kod poniżej.
źródło
Możesz użyć,
TextUtils.join(",", parameters)
aby skorzystać z parametrów wiązania sqlite, gdzieparameters
jest lista z"?"
symbolami zastępczymi, a ciąg wynikowy jest podobny do"?,?,..,?"
.Oto mały przykład:
źródło
Właściwie możesz użyć natywnego sposobu wykonywania zapytań Androida zamiast rawQuery:
źródło
To nie jest ważne
To jest ważne
Korzystanie z ContentResolver
źródło
W Kotlinie możesz użyć joinToString
źródło
Używam
Stream
API do tego:źródło