【问题标题】:Sqlite not updating rowsSqlite 不更新行
【发布时间】:2013-12-03 11:07:46
【问题描述】:

您好,我正在尝试更新一些行,增加 int 字段中的值,但它不起作用。 这是我的sn-p代码:

        SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
        queryBuilder.setTables("TICKET");
        String[] proj = new String[]{ "TICKET","NUMERO_ARTICOLO","QUANTITA","COMMESSA_IN","CODICE_SQUADRA"};
        try{
            Cursor cursor = queryBuilder.query(sqlDB, proj, selection, null, null, null, null);
            sqlDB.beginTransaction();
            cursor.moveToFirst();
            while (cursor.moveToNext()){
                String query =     "UPDATE MATERIALE "
                        + " SET RIMANENTE = RIMANENTE - " + cursor.getString(cursor.getColumnIndex("QUANTITA"))
                        + " WHERE NUMERO_ARTICOLO = '"+cursor.getString(cursor.getColumnIndex("NUMERO_ARTICOLO"))+"'"
                        +" AND COMMESSA = '"+cursor.getString(cursor.getColumnIndex("COMMESSA_IN"))+"' "
                        +" AND CODICE_SQUADRA = '"+cursor.getString(cursor.getColumnIndex("CODICE_SQUADRA"))+"' ";
                Log.d("update","Query: "+query);
                sqlDB.rawQuery(query, null);
            }
            rowsUpdated = sqlDB.update("TICKET", values, selection, null);
            sqlDB.setTransactionSuccessful();
            Log.d("update","Aggiornate "+rowsUpdated+" righe");
            sqlDB.endTransaction();
        }catch (Exception e) {
            e.printStackTrace();
        }

        break;
    default:
        throw new IllegalArgumentException("Unknown URI: " + uri);
    }
    getContext().getContentResolver().notifyChange(CONTENT_URI, null);
    return rowsUpdated;

最后一个查询正在运行

rowsUpdated = sqlDB.update("TICKET", values, selection, null);

但是 while 循环不起作用。 我做错了什么?也许更新SET RIMANENTE = RIMANENTE - " + cursor.getString(cursor.getColumnIndex("QUANTITA"))

我想要循环(while)和最后一次更新在同一个事务中。

【问题讨论】:

  • 单步执行代码时,光标是空的还是有行?
  • 你总是跳过第一行。 cursor.moveToFirst() 转到第一行,然后 while (cursor.moveToNext()) 将您移动到第二行以进行循环的第一次迭代。这是这里的问题吗?
  • cursor.moveToFirst() 是我没有输入真实代码的错字。游标不为空 我可以循环浏览游标但行没有更新。

标签: android sql sqlite transactions android-sqlite


【解决方案1】:

当您插入更新或从数据库中选择行时,Sqlite 使用基于文件的锁定。这意味着当您使用 Select 查询从数据库中获取记录时,直到带有 select 语句的 cursor 未关闭,您不能同时 insert updatedelete
所以你应该关闭cursor,然后用execSQL代替rawQuery来触发update

    try
    {
        Cursor cursor = queryBuilder.query(sqlDB, proj, selection, null, null, null, null);
        //sqlDB.beginTransaction();
        List<String> updateSql = new ArrayList<String>();
        try
        {
            cursor.moveToFirst();
            while (cursor.moveToNext())
            {
                updateSql.add(    "UPDATE MATERIALE "
                        + " SET RIMANENTE = RIMANENTE - " + cursor.getString(cursor.getColumnIndex("QUANTITA"))
                        + " WHERE NUMERO_ARTICOLO = '"+cursor.getString(cursor.getColumnIndex("NUMERO_ARTICOLO"))+"'"
                        +" AND COMMESSA = '"+cursor.getString(cursor.getColumnIndex("COMMESSA_IN"))+"' "
                        +" AND CODICE_SQUADRA = '"+cursor.getString(cursor.getColumnIndex("CODICE_SQUADRA"))+"' ");
                Log.d("update","Query: "+query);                    
            }
        } 
        finally
        {
            cursor.close();
        }
      try
      {
        sqlDB.beginTransaction();
        for (String query : updateSql)
        {
            sqlDB.execSQL(query, null); //Here it should be execSQL instead of rawQuery
        }
        rowsUpdated = sqlDB.update("TICKET", values, selection, null);

        sqlDB.setTransactionSuccessful();
        Log.d("update","Aggiornate "+rowsUpdated+" righe");
      }
      finally
      {
        sqlDB.endTransaction();
      }
    }
    catch (Exception e) 
    {
        e.printStackTrace();
    }

编辑如果我读到documentation,就会清楚地提到

对于 UPDATE 语句,请改用以下任一语句。
update(String, ContentValues, String, String[])
updateWithOnConflict(String, ContentValues, String,字符串[], int)

【讨论】:

  • 我尝试了您的建议,但 for 循环不起作用,没有错误,但行未使用新值更新。最后一个查询和以前一样工作。我在应用程序数据库的广告转储中尝试了循环查询,它们在我的电脑上工作。
  • 使用execSQL而不是rawQuery
  • 我尝试切换到 execSQL 并且表没有更新,当我尝试通过这里的应用程序访问 db 时结果:12-03 13:02:45.506: E/SQLiteDatabase(18803): Failed to open database '...databases/magazzino.db'. 12-03 13:02:45.506: E/SQLiteDatabase(18803): android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5): , while compiling: PRAGMA journal_mode
  • 您能否在执行后粘贴已存储在updateSql 数组中的更新查询以及数据表MATERIALE 的结构
  • 好的。如果您使用一个 execSQL(String query,String[] bindgArgs) 并将第二个参数设置为 null 我有一个异常,那么使用 execSQL(String query) 仅使用具有 1 个参数的方法会起作用。现在sqlDB.beginTransaction(); for (String query : updateSql) { Log.d("update","Query: "+query); sqlDB.execSQL(query); } rowsUpdated = sqlDB.update("TICKET", values, selection, null); sqlDB.setTransactionSuccessful(); Log.d("update","Aggiornate "+rowsUpdated+" righe"); sqlDB.endTransaction(); 那么现在是一笔交易了吗?
【解决方案2】:

您最好使用 SQL 工具来完成此任务:

try {
    sqlDB.execSQL("UPDATE TICKET SET RIMANENTE = RIMANENTE - QUANTITA");
} catch (Exception e) {
    e.printStackTrace();
}

这将在单个语句中 - 因此,也在单个事务中 - 从表 TICKET 的所有行中减去 QUANTITARIMANENTE

编辑:

UPDATE TICKET SET RIMANENTE = RIMANENTE - QUANTITA WHERE QUANTITA IS NOT NULL

更可取,因为如果未定义 QUANITTA,即 NULL,RIMANENTE 将被清空。 WHERE 子句防止这种情况发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多