2012-06-21 54 views
0

我无法让SQLite支持围绕多个插入的我的开始/结束事务。Android sqlite插入500行不起作用或保留INSERT命令

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()); 

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

回答

2

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

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

2

使用SQLiteDatabase.beginTransaction()SQLiteDatabase.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(); 
} 
+0

我试过了,但随后的插入顺序不保留。例如尝试插入“3”然后“1”。这是发生了什么事。 'select rowid,* from t_order;' '1 | 1' '3 | 3' – AG1

+0

@ AG1 - 我不认为如果您设法让您的多语句SQL查询工作。从[在另一个线程上回答此问题](http://stackoverflow.com/a/7597406/535871):_“按插入时间顺序对行进行排序的最佳实践方法是使用时间戳列这是作为默认值分配的日期时间对应于“现在”,因为该行正在插入。“_ –

+0

很遗憾sqlite不保留插入顺序。我意识到可以做一些简洁的优化,但在不需要的地方添加额外的数据列看起来很浪费。是否有任何命令会告诉sqlite在开始事务后保留插入顺序? – AG1

0

看一看上beginTransaction() Android官方文档。用一个执行单独execSQL()调用的循环替换“...”部分 - 不需要在一个缓冲区中一起截断语句。

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

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(); 
}