2012-02-26 11 views
5

API Seviye başarısız:SQLiteStatement (çoklu insert) yürütmek Bir DB etkili bir şekilde yeni satırlar eklemek için aşağıdaki kodu kullanabilirsiniz 14

@Override 
public void insertImpacts(HolderExpense expense, int[] shares, int[] amounts, HolderUser[] users) { 

    try { 

     mDb.beginTransaction(); // the insertion of the impacts of one expense are considered to be ONE block 

     String sql = "INSERT INTO "+DATABASE_TABLE_IMPACTS+" "+ 
     "("+IMPACT_USERROWID+", "+IMPACT_EXPENSEROWID+", "+IMPACT_TTROWID+", "+IMPACT_NUMBEROFPARTS+", "+IMPACT_FIXEDAMOUNT+") VALUES (?, ?, ?, ?, ?)"; 

     SQLiteStatement stmt = mDb.compileStatement(sql); 

     stmt.bindLong(2, expense.rowId); 
     stmt.bindLong(3, expense.tt.rowId); 

     int i = 0; 

     while (i < shares.length) { 

      if (users[i] != null) { 

       Log.v(TAG, "user " +i+": users[i].rowId:"+users[i].rowId+" expense.rowId:"+expense.rowId+" expense.tt.rowId:"+expense.tt.rowId+" shares[i]:"+shares[i]+" amounts[i]:"+amounts[i]+" "); 

       stmt.bindLong(1, users[i].rowId); 
       stmt.bindString(4, shares[i]+""); 
       stmt.bindString(5, amounts[i]+""); 

       stmt.execute(); 

      } 
      i++; 
     } 

     stmt.close(); 

     mDb.setTransactionSuccessful(); 

    } 
    catch (Exception e) { e.printStackTrace(); throw new RuntimeException("insertImpacts() failed"); } 
    finally { mDb.endTransaction(); } 

} 

o hata alıyorum nerede android 4.x kadar çalışır:

02-26 14:27:46.179: W/System.err(937): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed 

02-26 14:27:46.179: W/System.err(937): at android.database.sqlite.SQLiteStatement.native_execute(Native Method) 

02-26 14:27:46.219: W/System.err(937): at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:92) 

02-26 14:27:46.219: W/System.err(937): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:70) 

bu stmt.execute çakılacaktır görünüyor() tabloya ikinci satırı yerleştirirken.

Herhangi bir ipucu?

- EDITION - Tablonun

şema aşağıdadır:

private static final String DATABASE_CREATE_TABLE_IMPACTS = 
     "create table " + DATABASE_TABLE_IMPACTS + " (" 
     + IMPACT_ROWID + " integer primary key autoincrement, " 
     + IMPACT_USERROWID + " integer not null, " 
     + IMPACT_EXPENSEROWID + " integer not null, " 
     + IMPACT_TTROWID + " integer not null, " 
     + IMPACT_NUMBEROFPARTS + " integer not null, " 
     + IMPACT_FIXEDAMOUNT + " integer not null, " 
     + "constraint i_cstr1 unique ("+IMPACT_USERROWID+", "+IMPACT_EXPENSEROWID+")); "; 

Bu kod Android 2.2 üzerinde bir cazibe gibi çalışır (ama Android 4.0 başarısız). Ben eklemek heriki ilk satırdan

Baskı (ikinci eklemek çalışırken kilitleniyor):

02-26 14:27:46.069: E/DatabaseAdapter.java(937): user 0: users[i].rowId:7 expense.rowId:2 expense.tt.rowId:2 shares[i]:1 amounts[i]:-1 
02-26 14:27:46.069: E/DatabaseAdapter.java(937): user 1: users[i].rowId:5 expense.rowId:2 expense.tt.rowId:2 shares[i]:1 amounts[i]:-1 
+2

Kuyusu, görünüyor. Masa şemanın nedir? – Mat

+0

@Mat ile katılıyorum, create table deyiminizi göndermelisiniz. – dmon

+0

Merhaba Mat. Sorumu tablonun şemasıyla düzenledim. – Gilbou

cevap

10

buldum. Android'in farklı sürümü aynı şekilde davranmaz. Android 4.x'te, tüm 'bindXXX' satırları 'while' döngüsüne yerleştirilmelidir. Tekrarlayan bile olsa.

while (i < shares.length) { 

    if (users[i] != null) { 

     stmt.bindLong(1, users[i].rowId); 
     stmt.bindLong(2, expense.rowId); 
     stmt.bindLong(3, expense.tt.rowId); 
     stmt.bindString(4, String.valueOf(shares[i])); 
     stmt.bindString(5, String.valueOf(amounts[i])); 

     stmt.execute(); 
    } 

    i++; 

} 
+0

Mükemmel - bunun için teşekkürler. Asla ** TÜM ** parametrelerini 4.x –

+1

altında yeniden tanımlamayı düşünmemiştim Boolean değerleri nasıl bağlanır? –

+0

@Pratik: Cevabınızı henüz bulamadıysanız, ancak SQLite'ın bir boole türü olmadığından emin değilsiniz. Diğer tiplerden birini kullanmanız gerekir. 0/1 bir tam sayı kullanıyorum ve giriş/çıkışa dönüştürüyorum. –

1

Bu mükemmel Gilbou olduğunu! Ayrıca görevim için veri bağlama çözümünü yaptım: SQLite veritabanına içe aktarılan csv dosyası. Csv dosyasında yaklaşık 25.000 satır vardı, ve onu ithal etmek ve SQLite'ye eklemek yaklaşık 5 saniye sürüyor (veri bağlamadan 5 dakika sürmeden önce!)

Çok teşekkür ederim!

Ben de belki can (Android 4.0) de birisi için yardımcı olur, Benimkini: Bir kısıtlamayı ihlal konum gibi

public boolean updateFromCsv() { 

    boolean ok = true; 
    String line = ""; 
    BufferedReader br = null; 

    try { 
     FileInputStream fis = new FileInputStream(Environment 
       .getExternalStorageDirectory().getAbsolutePath() 
       + "/Servantes/Be/leltariv_export.csv"); 
     br = new BufferedReader(new InputStreamReader(fis)); 
    } catch (FileNotFoundException e) { 
     ok = false; 
     e.printStackTrace(); 
    }  
    try { 

     database.beginTransaction(); 

     String sql = "INSERT INTO "+LeltarTable.TABLE_LELTAR_NEV+" "+ 
     "("+LeltarTable.COLUMN_ID+", "+LeltarTable.COLUMN_LSZ+", "+LeltarTable.COLUMN_MEGN+", "+LeltarTable.COLUMN_HELY+", "+LeltarTable.COLUMN_DARAB+") VALUES (?, ?, ?, ?, 0)"; 

     SQLiteStatement stmt = database.compileStatement(sql); 

     while ((line = br.readLine()) != null) { 
      String[] colums = line.split(";"); 
      stmt.bindAllArgsAsStrings(colums); 
      stmt.execute(); 
} 
     stmt.close(); 

     database.setTransactionSuccessful(); 

    }catch (Exception e) { 
     e.printStackTrace(); 
     ok = false; 
    } 
    finally { 
     try { 
      br.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      ok = false; 
     } 
     database.endTransaction(); 
     } 

    return ok; 
} 
İlgili konular