Android: 批量插入,当InsertHelper被弃用时

18

许多答案和教程使用InsertHelper在SQLiteDatabase中进行快速批量插入。
但是从API 17开始,InsertHelper已被弃用。

现在在Android SQLite中批量插入大量数据的最快方法是什么?

到目前为止,我最关心的是SQLiteStatement不是很方便使用,而InsertHelper则具有绑定列和绑定值,这有点琐碎。

4个回答

26

SQLiteStatement还具有绑定方法,它是SQLiteProgram的扩展。

只需在事务中运行即可:


    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    final SQLiteStatement statement = db.compileStatement(INSERT_QUERY);
    db.beginTransaction();
    try {
        for(MyBean bean : list){
            statement.clearBindings();
            statement.bindString(1, bean.getName());
            // rest of bindings
            statement.execute(); //or executeInsert() if id is needed
        }
        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
    }

编辑

我在SQLiteQueryBuilder中找不到好的解决方案,但实际上可以这样简单做:

final static String INSERT_QUERY = createInsert(DbSchema.TABLE_NAME, new String[]{DbSchema.NAME, DbSchema.TITLE, DbSchema.PHONE});

static public String createInsert(final String tableName, final String[] columnNames) {
    if (tableName == null || columnNames == null || columnNames.length == 0) {
        throw new IllegalArgumentException();
    }
    final StringBuilder s = new StringBuilder();
    s.append("INSERT INTO ").append(tableName).append(" (");
    for (String column : columnNames) {
        s.append(column).append(" ,");
    }
    int length = s.length();
    s.delete(length - 2, length);
    s.append(") VALUES( ");
    for (int i = 0; i < columnNames.length; i++) {
        s.append(" ? ,");
    }
    length = s.length();
    s.delete(length - 2, length);
    s.append(")");
    return s.toString();
}

这很好,但INSERT_QUERY必须是纯文本编写的查询,其中包含内容值占位符“?”,对于大型数据集来说,这相当不便,不是吗? - Marek Sebera
没错,也许https://developer.android.com/reference/android/database/sqlite/SQLiteQueryBuilder.html可以帮助你? - pawelzieba
在你的回答中添加一些示例代码,我认为这可能是解决方案,之后我会接受你的回答。 - Marek Sebera
感谢提供代码...请注意绑定索引是从1开始的...你可能需要进行更正。 - Matthieu
statement.execute() 比直接使用 db.insert() 好吗?似乎为了不太大的好处而多写了几行代码。 - nucleartide
SQLiteStatement 要求我知道列索引,所以我又得为每个特定的表编写代码了(尽管 "createInsert" 帮助我处理了列名)。而 InsertHelper 可以从 ContentValues 中找出来。 - Victor Basso

1

我建议你看一下谷歌IO应用程序,特别是提供者,这就是谷歌开发人员的做法,所以你可以确定是正确的方式。


1
由于提供者(新URL)甚至没有实现bulkInsert,我认为他们并没有专注于速度。 - Jade

1

我曾经遇到同样的问题,无法找到SQLiteStatement如何轻松地替换DatabaseUtils.InsertHelper,因为你需要手动构建SQL查询。

最终我使用了SQLiteDatabase.insertOrThrow,它可以轻松地替换现有的代码。我只需要有时添加一个空列hack来处理插入空ContentValues的情况。

是的,该语句未编译以便以后重复使用,但手动构建INSERT查询并绑定所有参数太过繁琐。如果您修改代码,我很想知道这对于大量批量插入数据集(InsertHelper仅已弃用)的性能影响有多大。


1
我刚刚备份了默认类,只保留与InsertHelper相关的代码,请查看this gist
我相当确定这是为了清理SDK工具类而被弃用的。我的类中只使用未被弃用的内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接