在ContentProvider中使用"插入"或"替换"

tyc*_*czj 8 sqlite android android-contentprovider

当我想检查并查看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

}
Run Code Online (Sandbox Code Playgroud)

但这意味着我总是要做一个不必要的数据库调用,这会减慢速度,尤其是我需要对数据库进行更多的检查.必须有一个更好的方法来处理这个,所以我不必总是先查询.

我看了这个问题

Android Contentprovider - 在插入方法中更新

insertWithOnConflict只使用检查主键ID,在我的情况下,这将无法正常工作,因为我正在检查的不是id,而是来自服务器数据库的唯一字符串.

那么我可以用内容提供商做些什么,所以我不必总是要查询是否已经存在该项目?

Edu*_* B. 22

您可以对不同于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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望它有所帮助.干杯!


Nee*_*ama 5

Edy Bolos的答案可以简单地写成

CREATE TABLE TEST ( _id INTEGER PRIMARY KEY AUTOINCREMENT, server_id INTEGER NOT NULL, name TEXT UNIQUE ON CONFLICT REPLACE);

在create table query中添加UNIQUE ON CONFLICT REPLACE.

  • 它不一样,因为`ON CONFLICT REPLACE`将替换整行,可能会丢失一些列,而我的解决方案会更新您指定的列,而不会丢失其他列中的数据. (5认同)