2012-10-23 12 views
8

Ho creato correttamente un database SQLite e funziona correttamente. Tuttavia, quando viene chiamato il metodo onUpgrade, mi piacerebbe farlo senza perdere dati. L'app che sto sviluppando è un'app di quiz. Semplicemente, quando viene chiamato il metodo onCreate, creo e prepopolo un database con domande, risposte, ecc. L'ultima colonna indica se hanno impostato la domanda come preferita o meno. Quello che vorrei fare è che quando viene chiamato il metodo onUpgrade, vorrei salvare temporaneamente una colonna, eliminare l'intero database, ricrearlo con tutte le modifiche apportate alle vecchie domande e aggiungere eventuali nuove domande, quindi -adottare le domande che hanno impostato come preferiti.Aggiornamento SQLite Android senza perdita di dati

Quindi una possibilità che ho provato era il seguente:

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"); 

Tuttavia questo non funziona a causa del fatto INSERT INTO solo aggiunge nuove righe invece di sostituire le righe esistenti. Ho anche provato REPLACE INTO, INSERT O REPLACE INTO e

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

di cui nessuno funziona.

Attualmente sono impostato per funzionare modificando il nome della tabella, chiamando il metodo onCreate (db) e quindi impostando un cursore che legge ciascuna riga e utilizza il metodo db.update() come mostrato di seguito :

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(); 

} 

Tuttavia, mentre questo funziona è estremamente lento e sarà solo peggiorare come il mio numero di domande aumenta. C'è un modo rapido per fare tutto questo?

Grazie! Post scriptum Idealmente dovrebbe aggiornare la riga solo se la riga è presente. Quindi se in un aggiornamento decido di rimuovere una domanda, dovrebbe tenerne conto e non aggiungere una nuova riga se la riga non contiene altri dati. Potrebbe essere più facile ottenerlo per rimuovere le righe che non contengono dati delle domande piuttosto che impedire che vengano aggiunte.

risposta

3

cambiato in:

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)"); 

Quali opere: D

+2

penso tu intendessi "Aggiorna new_quiz", non old_quiz =) – hiBrianLee

+0

Scusa, questo è quello che intendevo . Grazie: D – AndroidPenguin

+0

@AndroidPenguin, modificato come hai detto nel tuo commento. –

1

Non ho visto lo schema della tabella dei quiz, ma presumo che abbia campi come "domanda", "risposta", "preferiti" e qualche tipo di chiave primaria univoca per identificare ogni domanda, che io chiamerò solo rowId per ora.

// 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"); 

che aggiornerà solo le righe della nuova tabella quiz che corrisponde alla vecchia tabella quiz, e impostare il valore preferiti dalla vecchia tabella quiz.

Suppongo che tu abbia un qualche tipo di identificatore univoco per identificare ogni domanda, quindi al posto del rowId in alto, lo userai (numero di domanda o qualcosa).

+0

che non ha funzionato:/mantenuto gettando errori con new_quiz.favourites dovuti al periodo. Modificato che poi solo per i preferiti, dove ancora non ha capito. Alla fine ho adattato la tua risposta con le mie dichiarazioni selezionate e l'ho fatta funzionare: D – AndroidPenguin

+0

ah Ho dimenticato che sqlite non supporta JOIN su 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

Le eccezioni di cattura in onCreate e onUpdate sono una cattiva idea poiché i valori restituiti da questi metodi vengono utilizzati per determinare se eseguire il rollback delle transazioni eseguite in – goonerify

2

Per chi non lo so ancora come aggiornare la versione del SQLite durante l'aggiornamento dello schema del database, ad esempio, l'uso il metodo needUpgrade (int newVersion)!

Il mio codice:

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

    if(newVersion>oldVersion){ 

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

} 
+3

'ononUpgrade()' viene sempre chiamato quando il valore 'newVersion' è sopra' oldVersion', quindi non c'è bisogno di quella dichiarazione if. – Saket

0
ALTER TABLE mytable ADD COLUMN mycolumn TEXT 

nel metodo ONUPGRADE, sarebbe simile a questa:

@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); 
} 
Problemi correlati