在Android设备上批量插入

Ron*_*ero 49 sqlite android bulkinsert

我希望在下次升级时将大约700条记录批量插入Android数据库.最有效的方法是什么?从各种帖子中,我知道如果我使用Insert语句,我应该将它们包装在一个事务中.还有一篇关于使用自己的数据库的帖子,但是我需要将这些数据放入我的应用程序的标准Android数据库中.请注意,每个设备只能执行一次.

一些想法:

  1. 将一堆SQL语句放在一个文件中,一次读取一行,然后执行SQL.

  2. 将数据放入CSV文件,JSON,YAML或XML等等.一次读一行,然后做db.insert().

  3. 弄清楚如何进行导入并对整个文件进行单次导入.

  4. 创建一个包含所有记录的sqlite数据库,将其复制到Android设备上,并以某种方式合并这两个数据库.

  5. [编辑]将所有SQL语句放在res/values中的单个文件中作为一个大字符串.然后一次读取一行并执行SQL.

什么是最好的方式?还有其他加载数据的方法吗?3和4甚至可能吗?

Jak*_*son 97

通常,每次db.insert()使用时,SQLite都会创建一个事务(以及文件系统中生成的日志文件),这会减慢速度.

如果你使用db.beginTransaction(),db.endTransaction()SQLite只在文件系统上创建一个日志文件,然后同时提交所有插入,大大加快了速度.

以下是一些伪代码:在Android上批量插入到SQLite数据库

try
{
  db.beginTransaction();

  for each record in the list
  {
    do_some_processing();

    if (line represent a valid entry)
    {
      db.insert(SOME_TABLE, null, SOME_VALUE);
    }

    some_other_processing();
  }

  db.setTransactionSuccessful();
}
catch (SQLException e) {}
finally
{
  db.endTransaction();
}
Run Code Online (Sandbox Code Playgroud)

如果您希望因意外错误或某事而中止事务,只需db.endTransaction()先将事务设置为success(db.setTransactionSuccessful())即可.

另一个有用的方法是使用db.inTransaction()(返回truefalse)来确定您当前是否处于事务中.

文档在这里

  • 有关更多代码参考:[在Android上批量插入到SQLite数据库](http://notes.theorbis.net/2010/02/batch-insert-to-sqlite-on-android.html) (2认同)
  • 这正是我所寻找的.我正在导入大约50个带有数千个记录的csv文件,完成后需要几个小时才能完成,从csv读取一行并将其插入数据库中.使用db.beginTransaction()只需要几秒钟!谢谢! (2认同)

Dan*_*lau 34

我发现对于批量插入,(显然很少使用)DatabaseUtils.InsertHelper类比使用快几倍SQLiteDatabase.insert.

另外两个优化也有助于我的应用程序的性能,尽管它们可能并不适用于所有情况:

  • 不要bind为空或者值null.
  • 如果您可以确定这样做是安全的,暂时关闭数据库的内部锁定也可以帮助提高性能.

我有一篇博文,内容更详细.

  • 对于记录:此类在API级别17中已弃用.请改用SQLiteStatement. (6认同)
  • 现在不推荐使用`InsertHelper`,我们被迫使用`SQLiteStatement`? (4认同)
  • [使用`SQLiteStatement`批量插入](http://stackoverflow.com/a/14344928/1276636) (2认同)

小智 9

好吧,我的解决方案有点奇怪,但工作正常......我编译了大量数据并一次性插入(批量插入?)

我使用db.execSQL(Query)命令,并使用以下语句构建"查询"...

INSERT INTO yourtable SELECT * FROM (
    SELECT 'data1','data2'.... UNION
    SELECT 'data1','data2'.... UNION
    SELECT 'data1','data2'.... UNION
    .
    .
    .
    SELECT 'data1','data2'....
)
Run Code Online (Sandbox Code Playgroud)

唯一的问题是查询的构建可能有点混乱.我希望它有所帮助


aru*_*n-r 9

以下示例将完美运行

 String sql = "INSERT INTO " + DatabaseHelper.TABLE_PRODUCT_LIST
                + " VALUES (?,?,?,?,?,?,?,?,?);";

        SQLiteDatabase db = this.getWritableDatabase();
        SQLiteStatement statement = db.compileStatement(sql);
        db.beginTransaction();
        for(int idx=0; idx < Produc_List.size(); idx++) {
            statement.clearBindings();
            statement.bindLong(1, Produc_List.get(idx).getProduct_id());
            statement.bindLong(2,  Produc_List.get(idx).getCategory_id());
            statement.bindString(3, Produc_List.get(idx).getName());
//            statement.bindString(4, Produc_List.get(idx).getBrand());
            statement.bindString(5, Produc_List.get(idx).getPrice());
            //statement.bindString(6, Produc_List.get(idx).getDiscPrice());
            statement.bindString(7, Produc_List.get(idx).getImage());
            statement.bindLong(8, Produc_List.get(idx).getLanguage_id());
            statement.bindLong(9, Produc_List.get(idx).getPl_rank());
            statement.execute();

        }
        db.setTransactionSuccessful();
        db.endTransaction();
Run Code Online (Sandbox Code Playgroud)


cod*_*ark 8

我不相信在你的名单上有任何可行的方法来完成#3或#4.

在其他解决方案中,您列出了两个数据文件包含直接SQL的数据库,另一个解决方案包含非SQL格式的数据.

这三个都可以正常工作,但后者建议从格式化文件中获取数据并自己构建SQL似乎是最干净的.如果以后添加了真正的批量更新功能,则您的数据文件仍然可用,或者至少可以轻松地处理为可用的表单.此外,数据文件的创建更简单,更不容易出错.最后,拥有"原始"数据将允许导入其他数据存储格式.

在任何情况下,您应该(如您所述)将插入组包装到事务中以避免创建每行事务日志.