当我想检查并查看我的ContentProvider
中是否存在某些内容时,我通常会做的与此相似
Cursor c = getContentResolver().query(table,projection,selection,selectionArgs,sort);
if(c != null && c.moveToFirst()){
//item exists so update
}else{
//item does not exist so insert
}
但这意味着我总是要做一个不必要的数据库调用,这会减慢速度,尤其是我需要对数据库进行更多的检查。必须有一个更好的方法来处理这个,所以我不必总是先查询。
我看了这个问题
Android Contentprovider - update within an insert method
但是使用insertWithOnConflict
只检查主键ID,在我的情况下,这将无效,因为我检查的不是id,而是来自服务器数据库的唯一字符串。
所以我可以对内容提供商做些什么,所以我不必总是进行查询以检查项目是否已经存在?
答案 0 :(得分:21)
您可以对不同于ID 1的列具有UNIQUE约束。例如:
CREATE TABLE TEST (_id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id INTEGER NOT NULL, name TEXT, UNIQUE(server_id))
拥有此表,在Content Provider的insert方法中,您可以执行以下操作:
@Override
public Uri insert(Uri uri, ContentValues contentValues) {
final SQLiteDatabase db = mDatabase.getWritableDatabase();
final int match = mUriMathcer.match(uri);
switch (match) {
case TEST:
insertOrUpdateById(db, uri, "TEST",
contentValues, "server_id");
getContext().getContentResolver().notifyChange(uri, null, false);
return Contract.Test.buildTestUri(contentValues.getAsString("server_id"));
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
/**
* In case of a conflict when inserting the values, another update query is sent.
*
* @param db Database to insert to.
* @param uri Content provider uri.
* @param table Table to insert to.
* @param values The values to insert to.
* @param column Column to identify the object.
* @throws android.database.SQLException
*/
private void insertOrUpdateById(SQLiteDatabase db, Uri uri, String table,
ContentValues values, String column) throws SQLException {
try {
db.insertOrThrow(table, null, values);
} catch (SQLiteConstraintException e) {
int nrRows = update(uri, values, column + "=?",
new String[]{values.getAsString(column)});
if (nrRows == 0)
throw e;
}
}
我希望它有所帮助。干杯!
答案 1 :(得分:5)
Edy Bolos答案可以简单地写成
CREATE TABLE TEST (
_id INTEGER PRIMARY KEY AUTOINCREMENT,
server_id INTEGER NOT NULL,
name TEXT UNIQUE ON CONFLICT REPLACE);
在创建表格查询中添加 UNIQUE ON CONFLICT REPLACE 。
答案 2 :(得分:1)
Edy Bolos的回答可以再次写成
private void insertOrUpdateById(SQLiteDatabase db, Uri uri, String table,
ContentValues values, String column)
throws Exception {
long id = db.insertWithOnConflict(table, column, values,
SQLiteDatabase.CONFLICT_REPLACE);
if(id < 0){
throw new Exception();
}
}
答案 3 :(得分:0)
使用REPLACE INTO代替INSERT INTO来解决问题