2013-11-08 4 views
5

Я хочу удалить все строки из таблицы, которые соответствуют идентификаторам в массиве. Я могу сделать это с помощью одного из двух методов (оба работают). Не могли бы вы посоветовать, какой из них лучше?Удалить несколько строк в SQLITE (android)

МЕТОД 1:

public void deleteRec(String[] ids) { //ids is an array 
     SQLiteDatabase db = this.getWritableDatabase(); 
     db.delete(TABLE_NAME, KEY_ID+" IN (" + new String(new char[ids.length-1]).replace("\0", "?,") + "?)", ids); 
     db.close(); 
    } 

МЕТОД 2:

public void deleteRec(String[] ids) { //ids is an array 
     String allid = TextUtils.join(", ", ids); 
     SQLiteDatabase db = this.getWritableDatabase(); 
     db.execSQL(String.format("DELETE FROM "+TABLE_NAME+" WHERE "+KEY_ID+" IN (%s);", allid)); 
     db.close(); 
    } 
+2

Для удобства чтения я предпочитаю второй метод. Но для производительности я не думаю, что это сильно повлияет. –

+0

читайте о транзакциях sqlite. – meh

ответ

6

Просто забыть о втором методе!

Ваши строки ids - это все строки из цифр (иначе SQL завершится с ошибкой), но для общих строковых данных передача данных в операторы SQL никогда не является хорошей идеей. Сделайте ваше приложение уязвимым для инъекции SQL:

String.format("DELETE FROM t WHERE ID='%s', "1' AND 1=1 --") 
// = "DELETE FROM t WHERE ID='1' AND 1=1 --'" => would delete all data! 

и может не ваши заявления SQL:

String.format("DELETE FROM t WHERE v='%s', "It's me!") 
// = "DELETE FROM t WHERE v='It's me!'" => syntactically incorrect (quote not escaped)! 

EDIT: Как ids поставляются в виде массива строк и, вероятно, KEY_ID относится к INT столбец, метод 1 должен быть адаптирован к:

db.delete(TABLE_NAME, "CAST("+KEY_ID+" AS TEXT) IN (" + new String(new char[ids.length-1]).replace("\0", "?,") + "?)", ids); 
+0

Как документация (http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#delete(java.lang.String, java.lang.String, java.lang.String [])): «Значения будут связаны как строки». Это означает, что указанная вами инъекция не будет работать, она будет интерпретироваться как текст и не анализироваться. –

+0

@ AndrasBalázsLajtha Правильно, но я предпочел бы использовать 'CAST' для конкатенации строк в SQL. –

+1

Выражение 'new String (new char [ids.length-1]). Replace (" \ 0 "," ?, ")' заслуживает объяснения: он создает массив 'char' с нулевым значением по умолчанию (' \ 0')), а затем заменяет эти нулевые значения на '?,' s. –

0

читать это documentation он говорит, что вы не должны использовать ExecSQL с INSERT, DELETE, UPDATE или ВЫБРАТЬ, потому что это может быть потенциальный риск безопасности , и все же я считаю, что в отношении производительности первый из них лучше.

+0

Второй способ можно изменить на 'db.delete (TABLE_NAME, KEY_ID +" IN (?) ", Новый String [] {allid});' следовать за документом. –

+0

@antimo ... это приятно и композитно .. Я попробую – abdfahim

+1

@antimo Нет, он не может !!! Существует масса вопросов о том, как класть массивы в предложение 'IN (...)'. –

-6

попробовать это

public void deleteRec(String[] ids) { //ids is an array 
    SQLiteDatabase db = this.getWritableDatabase(); 
    for (int i = 0; i < ids.length; i++) { 
     //Your code for delete 
    } 
    db.close(); 
} 
+0

он будет обращаться к базе данных 50 раз, если у меня есть 50 идентификаторов. Не уверен, что это хорошая идея. – abdfahim

+0

Это не отвечает на вопрос, и хуже, чем оба. –

+4

Анти-ответ. :) –

3

Попробуйте maybye это поможет вам:

String[] Ids = ......; //Array of Ids you wish to delete. 
String whereClause = String.format(COL_NAME + " in (%s)", new Object[] { TextUtils.join(",", Collections.nCopies(Ids.size(), "?")) }); 
db.delete(TABLE_NAME, whereClause, Ids); 
+2

Это то, что мне понравилось ..... это уменьшает написание для каждого цикла с помощью одного шага ... в конечном итоге это же .. создает динамический? в том месте. – karan

Смежные вопросы