Android:SQLite - insertWithOnConflict

时间:2012-09-11 02:20:17

标签: android sqlite insert

我使用SQLiteDatabase.CONFLICT_IGNORE调用insertWithOnConflict。但是,当发生冲突时,将返回“-1”而不是现有行的id。我该如何纠正?

创建表:

编辑:

String CREATE_CATEGORY_TABLE = "CREATE TABLE "+TABLE_CATEGORY+"(" +
    BaseColumns._ID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+
    KEY_CATEGORY_NAME+" TEXT UNIQUE" +
    ")";
db.execSQL(CREATE_CATEGORY_TABLE);

插入声明:

ContentValues values = new ContentValues();
values.put(KEY_CATEGORY_NAME, name);
int catID = (int) db.insertWithOnConflict(TABLE_CATEGORY, null, values, SQLiteDatabase.CONFLICT_IGNORE);

5 个答案:

答案 0 :(得分:9)

insertWithOnConflict,使用SQLiteDatabase.CONFLICT_IGNORE不能按预期工作,应该完全避免,因为这个问题:
https://code.google.com/p/android/issues/detail?id=13045

答案 1 :(得分:2)

SQLiteDatabase.CONFLICT_IGNORE注释的功能与您观察到的相同。在尝试插入时,如果没有冲突的行,则它将插入具有给定值的新行并返回新插入行的id。另一方面,如果已存在冲突的行(具有相同的唯一键),则将忽略传入的值并保留现有行,然后返回值将为-1以指示冲突场景。要了解更多详细信息并了解如何处理此返回值,请阅读Android/SQLite: Insert-Update table columns to keep the identifier

答案 2 :(得分:1)

Android希望将主键列调用_id。原因可能是:由于该列不存在,因此无法返回该值并返回-1。

答案 3 :(得分:1)

我使用的解决方法是使用insertOrThrow而不是insertWithOnConflict,并明确捕获SQLiteConstraintException。您需要明确地捕获它,因为它继承自RuntimeException

我不得不使用此解决方法,因为insert在发生冲突时将数据库方案转储到日志中,这是不可接受的。

答案 4 :(得分:0)

try {
        long id = db.insertWithOnConflict(StatusData.TABLE, null, values, SQLiteDatabase.CONFLICT_IGNORE);
        if (id == -1){
            throw new RuntimeException(String.format("%s: Failed to insert [%s] to [%s] for unkwon reason.",TAG,values,uri));
        }else
            return ContentUris.withAppendedId(uri, id);
    }

我仍然可以将行插入数据库,CONFLICT_IGNORE无法按预期工作@Tom是正确的但我不确定该问题是否已修复