使用ID删除多行?

问题描述:

如何通过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,则它被正确删除。但是,如果我提供多个值,则会影响零行。我究竟做错了什么?

当你给一个字符串作为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

每个“?”只会绑定到一个单一的值。所以,如果你的ID列表中有三个值,你whereClause将需要“_id IN(?,?,?)”

+0

但我传递的ID为由用逗号加盟值中的一个字符串。这是不允许的? – Natix 2014-10-07 01:36:30

+0

好点 - 您的whereArgs也需要是三个值的数组,而不是一个逗号分隔的字符串。 – eshayne 2014-10-07 01:42:02

不能使用whereArgsIN语句因逃逸通过whereArgs(除非你做每个值单独?) - 相反,你必须嵌入IDS在这里声明:

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