updateWithOnConflict()会发生什么样的冲突?

时间:2018-01-26 02:36:59

标签: android android-sqlite

我理解插入行可能会导致冲突,如果该行是重复的,但更新会导致什么样的冲突?我想不出任何一个。

换句话说,updateWithOnConflict()是什么?

3 个答案:

答案 0 :(得分:1)

冲突可能来自许多约束:主键,唯一,外键(如果启用)等。

想象一下,用户尝试将行_id更新为现有行。这会创建一个重复的行_id,这会导致与插入示例相同的冲突。

SQLite Column Constraint Diagram

以防万一,更新冲突不仅仅局限于Android的SQLite实现,it's fundamental to SQLite itself,但您可能知道这一点。

答案 1 :(得分:1)

来自文档:

The ON CONFLICT clause applies to UNIQUE, NOT NULL, CHECK, and PRIMARY KEY constraints

如果您更新某些内容,如果您有UNIQUE要求但更新使其不再唯一,或者您尝试使用null更新NOT NULL字段,则会失败。您还可以在表上拥有多个主键,并且永远不应更改这些主键。

这还取决于你如何使用它。也许您希望您的应用程序抛出异常,以便您可以捕获它并将其记录到某个地方,或者您可能不关心并且只想使用CONFLICT_REPLACE标志,这样您就不必考虑它。 / p>

答案 2 :(得分:1)

  

换句话说,updateWithOnConflict()是什么?

updateupdateWithOnConflict之间的主要区别在于后者将允许在发生冲突时采取行动(例如违反约束),而前者将导致异常(可能被困住了)。

简而言之,它在违反约束时提供更大程度的控制。但是,您也可以使用conflict-clause来做同样的事情(尽管冲突条款不能提供动态更改的灵活性)。

例如,假设一个表定义为: -

CREATE TABLE mytable (
    _id INTEGER PRIMARY KEY,           // IMPLIED CONSTRAINT UNIQUE NOT NULL
    thing_name TEXT UNIQUE,            // COLUMN CONSTRAINT UNIQUE
    table2_reference INTEGER NOT NULL, // COLUMN CONSTRAINT NOT NULL
    table3_reference INTEGER NOT NULL, // as previous
    CONSTRAINT table2_to_table3 UNIQUE // TABLE CONSTRAINT UNIQUE
        (table2_reference, table3_reference)
);

并填充: -

enter image description here

我们有一个更新方法,可以同时使用update和updateWithOnConflict,如: -

public void updateRow(
        long id,
        String newname,
        long newtable2ref,
        long newtable3ref,
        boolean with_on_conflict_flag) {
    if (id < 1) return;
    ContentValues cv = new ContentValues();
    if (newname != null && newname.length() > 0 ) {
        cv.put(COL_MYTABLE_THINGNAME,newname);
    }
    if (newtable2ref > 0) {
        cv.put(COL_MYTABLE_TBL2REF,newtable2ref);
    }
    if (newtable3ref > 0) {
        cv.put(COL_MYTABLE_TBL3REF,newtable3ref);
    }
    if (cv.size() > 0) {
        if (with_on_conflict_flag) {
            mDB.updateWithOnConflict(
                    TB_MYTABLE,cv,
                    COL_MYTABLE_ID + "=?",
                    new String[]{String.valueOf(id)},
                    SQLiteDatabase.CONFLICT_IGNORE //<<<< IGNORE exception
            );
        } else {
            mDB.update(
                    TB_MYTABLE,
                    cv, COL_MYTABLE_ID + "=?",
                    new String[]{String.valueOf(id)}
                    );
        }
    }
}

然后 mDBHlpr.updateRow(1,null,1,2,????); 使用两次

  • 先用????如 false
  • 然后使用 true
  • 即。强制执行约束违规,因为这会尝试创建非唯一组合( table2_reference和table3_reference的组合将匹配第二行)。

调用更新方法的第一个将导致异常并且App将停止,例如: -

android.database.sqlite.SQLiteConstraintException: columns table2_reference, table3_reference are not unique (code 19)

第二个陷阱错误忽略它(根据冲突算法),所以什么都不做(尽管日志将包含错误的堆栈跟踪)

请注意updateWithOnConflict方法的操作取决于第5个参数(上面使用了CONFLICT_IGNORE)。这里的冲突算法列表为er SQLiteDatabase: -

  

<强> CONFLICT_ABORT

     

发生约束违规时,不执行ROLLBACK,因此更改   来自同一事务中的先前命令的保留。

     

<强> CONFLICT_FAIL

     

发生约束违规时,命令将以返回方式中止   代码SQLITE_CONSTRAINT。

     

<强> CONFLICT_IGNORE

     

发生约束违规时,包含该行的一行   不插入或更改约束违规。

     

<强> CONFLICT_NONE

     

如果未指定冲突操作,请使用以下命令。

     

<强> CONFLICT_REPLACE

     

当发生UNIQUE约束违规时,预先存在的行   导致约束违反被删除之前插入或   更新当前行。

     

<强> CONFLICT_ROLLBACK

     

当发生约束违规时,会立即发生ROLLBACK   结束当前事务,命令以返回方式中止   SQLITE_CONSTRAINT的代码。