2012-10-23 36 views
8

Utworzono bazę SQLite pomyślnie i działa dobrze. Jednak po wywołaniu metody onUpgrade chciałbym to zrobić bez utraty danych. Aplikacja, którą tworzę, to aplikacja do quizów. Po prostu, gdy wywoływana jest metoda onCreate, tworzę i wstępnie wypełniam bazę danych pytaniami, odpowiedziami itp. Ostatnia kolumna określa, czy ustawiono pytanie jako ulubione, czy nie. Chciałbym to zrobić, gdy wywoływana jest metoda onUpgrade, chciałbym tymczasowo zapisać tę jedną kolumnę, upuścić całą bazę danych, odtworzyć ją za pomocą wszelkich zmian wprowadzonych do starych pytań i dodać nowe pytania, a następnie ponownie -od powrotem pytania, które ustawili jako ulubione.Aktualizacja Android SQLite bez utraty danych

Więc jedna opcja Próbowałem był następujący:

db.execSQL("ALTER TABLE quiz RENAME TO temp_quiz"); 
onCreate(db); 
db.execSQL("INSERT INTO quiz (favouries) SELECT favourites FROM temp_quiz"); 
db.execSQL("DROP TABLE IF EXISTS temp_quiz"); 

Jednak to nie działa ze względu na fakt INSERT INTO tylko dodaje nowe wiersze zamiast zastępując istniejące wiersze. Próbowałem również WYMIENIĆ, INSERT OR REPLACE INTO i

db.execSQL("INSERT INTO quiz (_id, favouries) SELECT _id, favourites FROM temp_quiz"); 

z czego żaden nie działa.

Obecnie mam to ustawione do pracy poprzez zmianę nazwy tabeli, wywołanie metody onCreate (db), a następnie ustawienie kursora, który odczytuje każdy wiersz i używa metody db.update(), jak pokazano poniżej :

int place = 1; 
int TOTAL_NUMBER_OF_ROWS = 500; 

while (place < TOTAL_NUMBER_OF_ROWS) { 

String[] columns = new String[] { "_id", ..........., "FAVOURITES" }; 
// not included all the middle columns 

Cursor c = db.query("temp_quiz", columns, "_id=" + place, null, null, null, null); 

c.moveToFirst(); 

String s = c.getString(10); 
// gets the value from the FAVOURITES column 


ContentValues values = new ContentValues(); 
values.put(KEY_FLAG, s); 

String where = KEY_ROWID + "=" + place; 

db.update(DATABASE_TABLE, values, where, null); 

place++; 

c.close(); 

} 

Mimo że działa to jest bardzo powolny i będzie tylko gorzej, jak moja liczba pytań wzrasta. Czy istnieje szybki sposób na zrobienie tego wszystkiego?

Dziękujemy! P.S. Idealnie powinien aktualizować tylko wiersz, jeśli wiersz jest obecny. Jeśli więc w aktualizacji zdecyduję się usunąć pytanie, należy wziąć to pod uwagę i nie dodawać nowego wiersza, jeśli wiersz nie zawiera żadnych innych danych. Może być łatwiejsze, aby usunąć wiersze, które nie zawierają danych pytań, zamiast zapobiegać ich dodawaniu.

Odpowiedz

3

zmienił go do:

db.execSQL("UPDATE new_quiz SET favourites = (SELECT old_quiz.favourites 
FROM old_quiz WHERE new_quiz._id = old_quiz._id) WHERE EXISTS 
(SELECT old_quiz.favourites FROM old_quiz WHERE new_quiz._id = old_quiz._id)"); 

który działa: D

+2

Myślę, że chodziło o "Update new_quiz", nie old_quiz =) – hiBrianLee

+0

Przepraszam, to co miałem na myśli . Dziękuję: D – AndroidPenguin

+0

@AndroidPenguin, zmodyfikowany zgodnie z Twoim komentarzem. –

1

Nie widziałem schematu tabeli quizu, ale zakładam, że ma ona pola takie jak "pytanie", "odpowiedź", "ulubione" i pewien rodzaj unikalnego klucza głównego do identyfikacji każdego pytania, które na razie zadzwoni na rowId.

// after renaming the old table and adding the new table 
db.execSQL("UPDATE new_quiz SET new_quiz.favorites = old_quiz.favorites where new_quiz.rowId = old_quiz.rowId"); 

To będzie aktualizować tylko wiersze nowej tabeli quizu, które pasują do starej tabeli sprawdzianu i ustawić wartość ulubione z starej tabeli quizu.

Zakładam, że masz jakiś unikatowy identyfikator identyfikujący każde pytanie, więc zamiast powyższego wiersza będziesz go używać (numer pytania lub coś w tym stylu).

+0

że nie działa:/rzucał błędy z powodu new_quiz.favourites do okresu. Zmieniono to na ulubione, gdzie wciąż nie rozumiem. Ostatecznie dostosowałem twoją odpowiedź z moimi wybranymi instrukcjami i dostałem to do pracy: D – AndroidPenguin

+0

ah Zapomniałem sqlite nie obsługuje JOIN na UPDATE = ( – hiBrianLee

2
public class DataHelper extends SQLiteOpenHelper { 

    private static final String dbName="dbName"; 
    private Context context; 
    private SQLiteDatabase db; 
    private final static int version = 1; 

    public static final String SurveyTbl = "CREATE TABLE SurveyTbl (SurveyId TEXT PRIMARY KEY, Idref TEXT, SurveyDate TEXT)"; 

    public DataHelper(Context context) { 

     super(context, dbName, null, version); 
     this.db = getWritableDatabase(); 
     this.context = context; 
     Log.i("", "********************DatabaseHelper(Context context)"); 
    } 



    @Override 
    public void onCreate(SQLiteDatabase db) { 

     try { 

     db.execSQL(SurveyTbl); 

     } catch (Exception e) { 
      Log.i("", "*******************onCreate"); 
     } 
    } 



    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 

     try { 
      db.execSQL("ALTER TABLE HandpumpSurveyTbl ADD COLUMN NalYozna TEXT"); 



     } catch (Exception e) { 
      Log.i("", ""+e); 
     } 


     onCreate(db); 


    } 
} 
+1

Łapanie wyjątków w trybie onCreate i onUpdate jest złym pomysłem, ponieważ zwrócone wartości z tych metod są używane do określenia, czy wycofać transakcje, które zostały wykonane w – goonerify

2

Na którzy jeszcze nie wiedzą, jak uaktualnić wersję SQLite podczas aktualizacji schematu bazy danych na przykład użyć metoda needUpgrade (int newVersion)!

Mój kod:

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){ 

    if(newVersion>oldVersion){ 

     db.execSQL(scriptUpdate); 
     db.needUpgrade(newVersion); 
    } 

} 
+3

'ononUpgrade()' jest zawsze wywoływane, gdy wartość 'nowaVersion' jest powyżej' oldVersion', więc nie ma takiej potrzeby, jeśli instrukcja. – Saket

0
ALTER TABLE mytable ADD COLUMN mycolumn TEXT 

W swojej metodzie ONUPGRADE, to będzie wyglądać mniej więcej tak:

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    String upgradeQuery = "ALTER TABLE mytable ADD COLUMN mycolumn TEXT"; 
    if (newVersion>oldVersion) 
     db.execSQL(upgradeQuery); 
} 
Powiązane problemy