2014-10-07 83 views
1

如何通過Android SQLite數據庫中的ID列表刪除多行?使用ID刪除多行?

我已經以這種方式定義的一般刪除方法:

protected void deleteWhere(String whereClause, String[] whereArgs) { 
    try { 
     databaseHelper.getWritableDatabase().delete(
       getTableName(), whereClause, whereArgs); 
    } finally { 
     databaseHelper.close(); 
    } 
} 

現在我想用ID列表來調用它:如果ID列表包含

public void deleteAll(Iterable<T> entities) { 
    Iterable<Long> ids = Iterables.transform(entities, getId); 

    String whereClause = getIdColumn() + " IN (?)"; 
    String[] whereArgs = { TextUtils.join(",", ids) }; 
    deleteWhere(whereClause, whereArgs); 
} 

例如值[1,2,42],那麼我假設生成的SQL應該是:

DELETE FROM tableName WHERE _id IN (1,2,42); 

但是,這似乎不工作co rrectly。如果列表僅包含1個ID,則它被正確刪除。但是,如果我提供多個值,則會影響零行。我究竟做錯了什麼?

回答

3

當你給一個字符串作爲whereArgs,一個字符串中的SQL命令結束了,因爲如果你寫了這個:

... WHERE _id IN ('1,2,42') 

這將比較每個_id的值與值'1,2,42',這當然不起作用。

如果使用三個參數標記和whereArgs數組中給三根弦,你最終會用三根弦,像這樣:

... WHERE _id in ('1','2','42') 

這隻能當_id列具有integer affinity,這是對於聲明爲INTEGER PRIMARY KEY的列爲true,但在一般情況下不適用。

Android數據庫API不允許查詢參數具有任何類型但字符串。 當使用整數時,你應該直接插入(在ianhanniballake's answer):

String whereClause = getIdColumn() + " IN (" + TextUtils.join(",", ids) + ")"; 
+0

哦,現在當我看到撇號被添加到值的方式時,這是有道理的。但是,是不是將值直接放入'whereClause'傾向於SQL注入?用適當數量的問號手動生成'whereClause'並將ID作爲String數組傳遞給'whereArgs'不是更好嗎? – Natix 2014-10-07 08:38:31

+0

僅允許字符串作爲參數是Android數據庫API設計中的一個錯誤。無論如何,整數值對SQL注入是安全的;此問題僅出現在字符串中。 – 2014-10-07 08:40:36

0

每個「?」只會綁定到一個單一的值。所以,如果你的ID列表中有三個值,你whereClause將需要「_id IN(?,?,?)」

+0

但我傳遞的ID爲由用逗號加盟值中的一個字符串。這是不允許的? – Natix 2014-10-07 01:36:30

+0

好點 - 您的whereArgs也需要是三個值的數組,而不是一個逗號分隔的字符串。 – eshayne 2014-10-07 01:42:02

2

不能使用whereArgsIN語句因逃逸通過whereArgs(除非你做每個值單獨?) - 相反,你必須嵌入IDS在這裏聲明:

String whereClause = getIdColumn() + " IN (" + TextUtils.join(",", ids) + ")"; 
deleteWhere(whereClause, null);