SQLite
 sql >> Database >  >> RDS >> SQLite

Inserisci o Aggiorna SQLite Android

Credo che tu stia chiedendo come INSERIRE nuove righe o AGGIORNARE le righe esistenti in un solo passaggio. Sebbene ciò sia possibile in un singolo SQL non elaborato come discusso in questa risposta, ho scoperto che è più facile farlo in due passaggi in Android usando SQLiteDatabase.insertWithOnConflict() usando CONFLICT_IGNORE per conflictAlgorithm.

ContentValues initialValues = new ContentValues();
initialValues.put("_id", 1); // the execution is different if _id is 2
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"});  // number 1 is the _id here, update to variable for your code
}

Questo esempio presuppone che la chiave della tabella sia impostata per la colonna "_id", che tu conosca il record _id e che sia già presente la riga n. 1 (_id=1, colonnaA ="valoreA", colonnaB ="valoreB"). Ecco la differenza usando insertWithOnConflict con CONFLICT_REPLACE e CONFLICT_IGNORE

  • CONFLICT_REPLACE sovrascriverà i valori esistenti in altre colonne su null (ad es. la colonnaB diventerà NULL e il risultato sarà _id=1, colonnaA ="valoreNEW", colonnaB =NULL). Di conseguenza, perdi i dati esistenti e non li uso nel mio codice.
  • CONFLICT_IGNORE salterà l'SQL INSERT per la tua riga esistente n. 1 e AGGIORNERAI SQL questa riga nel passaggio successivo preservando il contenuto di tutte le altre colonne (es. il risultato sarà _id=1, columnA ="valueNEW", colonnaB ="valoreB").

Quando si tenta di inserire una nuova riga n. 2 che non esiste ancora, il codice eseguirà solo SQL INSERT nella prima istruzione insertWithOnConflict (ad es. il risultato sarà _id=2, columnA ="valueNEW", columnB =NULL).

Fai attenzione a questo bug che causa il malfunzionamento di SQLiteDatabase.CONFLICT_IGNORE su API10 (e probabilmente API11). La query restituisce 0 anziché -1 quando eseguo il test su Android 2.2.

Se non conosci la chiave del record _id o hai una condizione che non creerà un conflitto, puoi invertire la logica su UPDATE o INSERT . Ciò manterrà la chiave del record _id durante UPDATE o creerà un nuovo record _id durante INSERT.

int u = yourdb.update("yourtable", values, "anotherID=?", new String[]{"x"});
if (u == 0) {
    yourdb.insertWithOnConflict("yourtable", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}

L'esempio sopra presuppone che tu voglia solo AGGIORNARE il valore del timestamp nel record, ad esempio. Se chiami prima insertWithOnConflict, INSERT creerà un nuovo record _id a causa della differenza nella condizione del timestamp.