我希望在下次升级时将大约700条记录批量插入Android数据库。最有效的方法是什么?从各种帖子中,我知道如果我使用Insert
语句,我应该将它们包装在一个事务中。关于使用您自己的数据库还有一个post,但我需要将这些数据放入我的应用程序的标准Android数据库中。请注意,每个设备只能执行一次。
一些想法:
将一堆SQL语句放在一个文件中,一次读取一行,然后执行SQL。
将数据放入CSV文件,JSON,YAML或XML等等。一次阅读一行,然后执行db.insert()
。
弄清楚如何进行导入并对整个文件进行一次导入。
创建一个包含所有记录的sqlite数据库,将其复制到Android设备上,并以某种方式合并这两个数据库。
[编辑]将所有SQL语句放在res / values中的单个文件中作为一个大字符串。然后一次读取一行并执行SQL。
最好的方法是什么?还有其他加载数据的方法吗? 3和4甚至可能吗?
答案 0 :(得分:97)
通常,每次使用db.insert()
时,SQLite都会创建一个事务(以及文件系统中生成的日志文件),这会减慢速度。
如果你使用db.beginTransaction()
和db.endTransaction()
SQLite只在文件系统上创建一个日志文件,然后同时提交所有插入,大大加快了速度。
以下是来自Batch insert to SQLite database on Android
的伪代码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();
}
如果您希望因意外错误或某事而中止交易,只需db.endTransaction()
而不先将交易设置为成功(db.setTransactionSuccessful()
)。
另一个有用的方法是使用db.inTransaction()
(返回true
或false
)来确定您当前是否处于交易过程中。
答案 1 :(得分:34)
我发现对于批量插入,(显然很少使用)DatabaseUtils.InsertHelper类比使用SQLiteDatabase.insert
快几倍。
另外两项优化也有助于我的应用程序的性能,但它们可能并不适用于所有情况:
bind
空值或null
。我有一个blog post,其中包含更多详细信息。
答案 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'....
)
唯一的问题是查询的构建可能有点混乱。 我希望它有所帮助
答案 3 :(得分: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();
答案 4 :(得分:8)
我不相信有任何可行的方法可以在你的名单上完成#3或#4。
在其他解决方案中,列出两个数据文件包含直接SQL,另一个包含非SQL格式的数据。
这三个都可以正常工作,但后者建议从格式化文件中获取数据并自己构建SQL似乎是最干净的。如果以后添加了真正的批量更新功能,则您的数据文件仍然可用,或者至少可以轻松地处理为可用的表单。此外,数据文件的创建更简单,更不容易出错。最后,拥有“原始”数据将允许导入其他数据存储格式。
在任何情况下,您应该(如您所述)将插入组包装到事务中,以避免创建每行事务日志。