我认为你想知道如何在一步中插入新行或更新现有行。虽然可以在单个原始 SQL 中完成,如此答案所讨论的那样,但我发现在Android中使用SQLiteDatabase.insertWithOnConflict()的CONFLICT_IGNORE冲突算法进行两步操作更容易。
ContentValues initialValues = new ContentValues();
initialValues.put("_id", 1);
initialValues.put("columnA", "valueNEW");
int id = (int) yourdb.insertWithOnConflict("your_table", null, initialValues, SQLiteDatabase.CONFLICT_IGNORE);
if (id == -1) {
yourdb.update("your_table", initialValues, "_id=?", new String[] {"1"});
}
假设这个示例假定表格的键设置为列 "_id",您知道记录 _id,并且已经有了第一行(_id = 1,columnA = "valueA",columnB = "valueB")。这里是使用 insertWithOnConflict 和 CONFLICT_REPLACE 以及 CONFLICT_IGNORE 的不同之处:
- CONFLICT_REPLACE 将覆盖其他列中的现有值为 null(即 columnB 将变为 NULL,结果将是 _id = 1,columnA = "valueNEW",columnB = NULL)。您将失去现有数据作为结果,我在我的代码中不使用它。
- CONFLICT_IGNORE 将跳过 SQL INSERT 的现有行 #1,您将在下一步中对此行进行 SQL UPDATE,保留所有其他列的内容(即结果将是 _id = 1,columnA = "valueNEW",columnB = "valueB")。
当您尝试插入尚不存在的新行 #2 时,代码将仅执行第一个语句 insertWithOnConflict 中的 SQL INSERT(即结果将是 _id = 2,columnA = "valueNEW",columnB = NULL)。
请注意 此错误 会导致 SQLiteDatabase.CONFLICT_IGNORE 在 API10 上(可能也是 API11)无法正常工作。当我在 Android 2.2 上测试时,查询返回 0 而非 -1。
如果您不知道记录键 _id 或者您有一个不会创建冲突的条件,您可以 倒转逻辑来进行 UPDATE 或 INSERT。这将在 UPDATE 期间保留您的记录键 _id,或在 INSERT 期间创建新的记录 _id。
int u = yourdb.update("yourtable", values, "anotherID=?", new String[]{"x"});
if (u == 0) {
yourdb.insertWithOnConflict("yourtable", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
上面的示例假设您只想更新记录中的时间戳值。如果您先调用insertWithOnConflict,则由于时间戳条件的差异,插入操作将创建新的记录_id。