我理解插入行可能会导致冲突,如果该行是重复的,但更新会导致什么样的冲突?我想不出任何一个。
换句话说,updateWithOnConflict()
是什么?
答案 0 :(得分:1)
冲突可能来自许多约束:主键,唯一,外键(如果启用)等。
想象一下,用户尝试将行_id
更新为现有行。这会创建一个重复的行_id
,这会导致与插入示例相同的冲突。
以防万一,更新冲突不仅仅局限于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()
是什么?
update
和updateWithOnConflict
之间的主要区别在于后者将允许在发生冲突时采取行动(例如违反约束),而前者将导致异常(可能被困住了)。
简而言之,它在违反约束时提供更大程度的控制。但是,您也可以使用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)
);
并填充: -
我们有一个更新方法,可以同时使用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,????);
使用两次
调用更新方法的第一个将导致异常并且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的代码。