Android / SQLite: Insertar-Actualizar columnas de la tabla para mantener el identificador

Actualmente, estoy usando la siguiente declaración para crear una tabla en una base de datos SQLite en un dispositivo Android.

CREATE TABLE IF NOT EXISTS 'locations' (
  '_id' INTEGER PRIMARY KEY AUTOINCREMENT, 'name' TEXT, 
  'latitude' REAL, 'longitude' REAL, 
  UNIQUE ( 'latitude',  'longitude' ) 
ON CONFLICT REPLACE );

La cláusula de conflicto al final hace que las filas seancaído Cuando se hacen nuevas inserciones que vienen con las mismas coordenadas. losDocumentación de SQLite Contiene más información sobre la cláusula de conflicto.

En cambio, me gustaríamantener las filas anteriores y justoactualizar sus columnas. ¿Cuál es la forma más eficiente de hacer esto en un entorno Android / SQLite?

Como una cláusula de conflicto en elCREATE TABLE declaración.Como unINSERT desencadenar.Como cláusula condicional en elContentProvider#insert método.... mejor que puedas pensar

Creo que es más eficaz manejar estos conflictos dentro de la base de datos. Además, me resulta difícil reescribir elContentProvider#insert método para considerar elinsertar-actualizar guión. Aquí está el código de lainsert método:

public Uri insert(Uri uri, ContentValues values) {
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    long id = db.insert(DatabaseProperties.TABLE_NAME, null, values);
    return ContentUris.withAppendedId(uri, id);
}

Cuando los datos llegan del servidor, todo lo que hago es insertar los datos de la siguiente manera.

getContentResolver.insert(CustomContract.Locations.CONTENT_URI, contentValues);

Tengo problemas para averiguar cómo aplicar una llamada alternativa aContentProvider#update aquí. Además, esta no es mi solución favorita de todos modos.

Editar:

@CommonsWare: traté de implementar su sugerencia de usoINSERT OR REPLACE. Se me ocurrió este código feo.

private static long insertOrReplace(SQLiteDatabase db, ContentValues values, String tableName) {
    final String COMMA_SPACE = ", ";
    StringBuilder columnsBuilder = new StringBuilder();
    StringBuilder placeholdersBuilder = new StringBuilder();
    List<Object> pureValues = new ArrayList<Object>(values.size());
    Iterator<Entry<String, Object>> iterator = values.valueSet().iterator();
    while (iterator.hasNext()) {
        Entry<String, Object> pair = iterator.next();
        String column = pair.getKey();
        columnsBuilder.append(column).append(COMMA_SPACE);
        placeholdersBuilder.append("?").append(COMMA_SPACE);
        Object value = pair.getValue();
        pureValues.add(value);
    }
    final String columns = columnsBuilder.substring(0, columnsBuilder.length() - COMMA_SPACE.length());
    final String placeholders = placeholderBuilder.substring(0, placeholdersBuilder.length() - COMMA_SPACE.length());
    db.execSQL("INSERT OR REPLACE INTO " + tableName + "(" + columns + ") VALUES (" + placeholders + ")", pureValues.toArray());

    // The last insert id retrieved here is not safe. Some other inserts can happen inbetween.
    Cursor cursor = db.rawQuery("SELECT * from SQLITE_SEQUENCE;", null);
    long lastId = INVALID_LAST_ID;
    if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
        lastId = cursor.getLong(cursor.getColumnIndex("seq"));
    }
    cursor.close();
    return lastId;
}

Cuando reviso la base de datos SQLite, sin embargo, las columnas iguales sonTodavía eliminado e insertado con nuevos identificadores. No entiendo por qué sucede esto y pensé que la razón es mi cláusula de conflicto. Pero eldocumentación Dice lo contrario.

El algoritmo especificado en la cláusula OR de un INSERT o UPDATEanula Cualquier algoritmo especificado en un CREATE TABLE. Si no se especifica ningún algoritmo en ninguna parte, se usa el algoritmo ABORTO.

Otra desventaja de este intento es que pierde el valor del ID que es devuelto por una declaración de inserción. Para compensar esto, finalmente encontré una opción para solicitar ellast_insert_rowid. Es como se explicaen los puestos de dtmilano y swiz. Sin embargo, no estoy seguro de si esto es seguro ya que puede haber otro inserto entre ellos.

Respuestas a la pregunta(5)

Su respuesta a la pregunta