0

我无法让 SQLite 支持围绕多个插入的开始/结束事务。

 Multiples INSERTs : 2500ms
 Using BEGIN and COMMIT : 90ms
 Using SELECT and UNION : 40ms

所以我看着使用开始和提交。我究竟做错了什么?

  // pseudocode: 
  ArrayList<Integer> iList = new ArrayList<Integer>();
    for (int i = 1; i <= 500; i++) {
      iList.add(i);
    }
  Collections.shuffle(iList);

  StringBuilder sb = new StringBuilder("begin transaction;");
  for (Integer i: iList) {
    sb.append("insert into \"t_order\" (qid) values(");
    sb.append(i);
    sb.append(");");
  }
  sb.append(" end transaction;");

  // from docs: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#execSQL(java.lang.String)
  // Execute a single SQL statement that is NOT a SELECT or any other SQL statement that returns data.
  m_db.execSQL(sb.toString());

好的,我做了更多研究,似乎“不支持用分号分隔的多个语句”。我可以做些什么来插入和保留插入顺序?

4

4 回答 4

2

启动事务,在单独的execSQL()调用中执行每个 INSERT,然后提交事务。

您不需要在同一个execSQL()调用中将 INSERT 聚集在一起。

于 2012-06-21T02:20:21.130 回答
2

使用SQLiteDatabase.beginTransaction()andSQLiteDatabase.endTransaction()方法并在它们之间发出 execSQL 调用。ContentValues使用结构而不是进行自己的字符串连接也是更好的风格:

ContentValues cv = new ContenValues();
m_db.beginTransaction();
try {
    for (Integer i: iList) {
        cv.put("qid", i);
        m_db.insert("t_order", null, cv);
    }
    m_db.setTransactionSuccessful();
} finally {
    m_db.endTransaction();
}
于 2012-06-21T02:20:55.480 回答
0

这可能会有所帮助:

public void putAll(Context context, LinkedList<HANDLEDOBJECT> objects) {

    if (objects.size() < 1 || objects.get(0) == null)
        return;

    Log.i("Database", "Starting to insert objects to " + getTableName());

    List<String> insertCommands = new ArrayList<String>();
    int t = 0;

    while (t < objects.size()) {
        int k = 0;
        StringBuilder sb = new StringBuilder();

        sb.append("INSERT OR REPLACE INTO ").append(getTableName())
                .append("('k', 'v') ");

        for (t = t + 0; t < objects.size() && k < 450; t++) {
            k++;
            if (t % 450 != 0)
                sb.append("UNION ");
            sb.append("SELECT " + objects.get(t).getId())
                    .append(" AS k, ")
                    .append("'"
                            + GsonSerializer.getInstance().toJson(
                                    objects.get(t), getHandledObjectType())
                            + "'").append(" AS v ");
        }

        insertCommands.add(sb.toString());
    }

    for (String insertCommand : insertCommands)
        SQLiteClient.getConnetion(context).execSQL(insertCommand);

    Log.i("Database", "Successfully inserted " + t + " objects to "
            + getTableName() + "!!!");

    System.gc();
}
于 2013-09-28T19:40:07.937 回答
0

查看有关beginTransaction()的官方 Android 文档。将“...”部分替换为执行单独的 execSQL() 调用的循环——无需将语句一起截断在一个缓冲区中。

此外,使用准备好的语句通常是值得的。准备语句,开始事务,循环每个项目绑定并执行语句,最后提交。

于 2012-06-21T02:35:36.797 回答