Uważam, że pytasz, jak WSTAWIĆ nowe wiersze lub ZAKTUALIZOWAĆ istniejące w jednym kroku. Chociaż jest to możliwe w pojedynczym surowym SQL, jak omówiono w tej odpowiedzi, stwierdziłem, że łatwiej jest to zrobić w dwóch krokach w systemie Android przy użyciu SQLiteDatabase.insertWithOnConflict() przy użyciu CONFLICT_IGNORE dla 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
}
W tym przykładzie założono, że klucz tabeli jest ustawiony dla kolumny „_id”, że znasz rekord _id i że istnieje już wiersz nr 1 (_id=1, kolumnaA =„wartośćA”, kolumnaB =„wartośćB”). Oto różnica przy użyciu insertWithOnConflict z CONFLICT_REPLACE i CONFLICT_IGNORE
- CONFLICT_REPLACE nadpisze istniejące wartości w innych kolumnach na null (tj. kolumna B stanie się NULL, a wynikiem będzie _id=1, kolumnaA ="wartośćNEW", kolumnaB =NULL). W rezultacie tracisz istniejące dane i nie używam ich w moim kodzie.
- CONFLICT_IGNORE pominie INSERT SQL dla istniejącego wiersza #1, a w następnym kroku wykonasz polecenie SQL UPDATE, zachowując zawartość wszystkich pozostałych kolumn (tj. wynikiem będzie _id=1, columnA ="valueNEW", kolumnaB ="wartośćB").
Przy próbie wstawienia nowego wiersza #2, który jeszcze nie istnieje, kod wykona tylko SQL INSERT w pierwszej instrukcji insertWithOnConflict (tzn. wynikiem będzie _id=2, kolumnaA ="wartośćNEW", kolumnaB =NULL).
Uważaj na ten błąd, który powoduje awarię SQLiteDatabase.CONFLICT_IGNORE w API10 (i prawdopodobnie API11). Zapytanie zwraca 0 zamiast -1, gdy testuję na Androidzie 2.2.
Jeśli nie znasz klucza rekordu _id lub masz warunek, który nie spowoduje konfliktu, możesz odwrócić logikę na UPDATE lub INSERT . Dzięki temu Twój klucz rekordu _id zostanie zachowany podczas aktualizacji lub zostanie utworzony nowy rekord _id podczas INSERT.
int u = yourdb.update("yourtable", values, "anotherID=?", new String[]{"x"});
if (u == 0) {
yourdb.insertWithOnConflict("yourtable", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
Powyższy przykład zakłada, że na przykład chcesz zaktualizować wartość znacznika czasu w rekordzie. Jeśli najpierw wywołasz insertWithOnConflict, INSERT utworzy nowy rekord _id ze względu na różnicę w warunku znacznika czasu.