2010-08-06 9 views
13

मुझे Logcat से एक त्रुटि मिल रही है जिसमें कहा गया है कि एक निश्चित कॉलम (मेरे SQLiteOpenHelper सबक्लास में) मौजूद नहीं है। मैंने सोचा कि मैं DATABASE_CREATE स्ट्रिंग को बदलकर डेटाबेस को अपग्रेड कर सकता हूं। लेकिन स्पष्ट रूप से नहीं, तो मैं (चरण-दर-चरण) संस्करण 1 से संस्करण 2 में अपने SQLite डेटाबेस को अपग्रेड कैसे कर सकता हूं?SQLite डेटाबेस को एक संस्करण से दूसरे संस्करण में अपग्रेड करें?

अगर माफी माँगती है तो सवाल "नोबिश" लगता है, लेकिन मैं अभी भी एंड्रॉइड के बारे में सीख रहा हूं।

@ Pentium10 यह है कि मैं क्या onUpgrade में क्या है:

private static final int DATABASE_VERSION = 1; 

.... 

switch (upgradeVersion) { 
case 1: 
    db.execSQL("ALTER TABLE task ADD body TEXT"); 
    upgradeVersion = 2; 
    break; 
} 

... 
+0

यह भी देखें https://stackoverflow.com/questions/8133597/android-upgrading-db-version-and-adding-new-table – Suragch

उत्तर

46

ठीक है, इससे पहले कि आप बड़ी समस्याओं में चलाने आपको पता होना चाहिए कि SQLite ALTER तालिका आदेश पर ही सीमित है, यह add और rename केवल कोई निकालने की अनुमति देता है/ड्रॉप जो मेज के मनोरंजन के साथ किया जाता है।

आपके पास हमेशा नई टेबल निर्माण क्वेरी होना चाहिए, और किसी भी मौजूदा डेटा को अपग्रेड और ट्रांसफर करने के लिए इसका उपयोग करना चाहिए। नोट: कि ऑन अपग्रेड विधियां आपके स्क्लाइट सहायक ऑब्जेक्ट के लिए एक चलाती हैं और आपको इसमें सभी तालिकाओं को संभालने की आवश्यकता होती है।

तो क्या सिफारिश की है onUpgrade:

  • beginTransaction
  • if not exists के साथ एक मेज निर्माण चलाने
  • (हम एक उन्नत कर रहे हैं, तो तालिका अभी तक मौजूद नहीं हो सकता है, यह परिवर्तन और ड्रॉप असफल हो जायेगी)
  • वर्तमान कॉलम List<String> columns = DBUtils.GetColumns(db, TableName);
  • बैकअप तालिका (ALTER table " + TableName + " RENAME TO 'temp_" + TableName)
  • नई तालिका बनाने के (सबसे नया तालिका बनाने रों एक सूची में डाल दिया chema)
  • नए कॉलम के साथ चौराहे मिलता है, इस समय के लिए उन्नत तालिका से लिया कॉलम (columns.retainAll(DBUtils.GetColumns(db, TableName));)
  • बहाल डेटा (String cols = StringUtils.join(columns, ","); db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", TableName, cols, cols, TableName)); )
  • निकालें बैकअप तालिका (DROP table 'temp_" + TableName)
  • setTransactionSuccessful

public static List<String> GetColumns(SQLiteDatabase db, String tableName) { 
    List<String> ar = null; 
    Cursor c = null; 
    try { 
     c = db.rawQuery("select * from " + tableName + " limit 1", null); 
     if (c != null) { 
      ar = new ArrayList<String>(Arrays.asList(c.getColumnNames())); 
     } 
    } catch (Exception e) { 
     Log.v(tableName, e.getMessage(), e); 
     e.printStackTrace(); 
    } finally { 
     if (c != null) 
      c.close(); 
    } 
    return ar; 
} 

public static String join(List<String> list, String delim) { 
    StringBuilder buf = new StringBuilder(); 
    int num = list.size(); 
    for (int i = 0; i < num; i++) { 
     if (i != 0) 
      buf.append(delim); 
     buf.append((String) list.get(i)); 
    } 
    return buf.toString(); 
} 
+0

क्या मैं तालिका तैयार करने के बजाय EXEMSTS नहीं बना सकता था अगर मैं तालिका नहीं बना सकता तो EXISTS ? –

+0

नहीं, क्योंकि जब कनेक्शन गिरता है तो आप इसे खो देंगे। हमेशा अपनी तालिका स्कीमा को 'तालिका बनाएं यदि EXISTS' – Pentium10

+0

डेटाबेस के संस्करण को कैसे शामिल करता है' के रूप में रखें? –

1

यहां बताया गया है कि मैं अपना डेटाबेस कैसे अपग्रेड करता हूं।

मेरे ऐप के पिछले संस्करण में, gameType कॉलम मौजूद नहीं है। नए संस्करण में, यह करता है।

void upgradeDatabase() throws IOException { 
    try { 
     String column = DatabaseConstants.GAME_TYPE_COLUMN_NAME; // gameType 
     String table = DatabaseConstants.RECORDS_TABLE; 
     String query = String.format("SELECT %s FROM %s LIMIT 1", column, table); 
     database.rawQuery(query, null); 
     return; 
    } 
    catch (Exception e) { 
     // Column doesn't exist. User had old version of app installed, so upgrade database. 
    } 

    // Save all old data 
    String query = "SELECT * FROM " + DatabaseConstants.USERS_TABLE; 
    Cursor c = database.rawQuery(query, null); 
    List<List<Object>> values1 = new ArrayList<List<Object>>(); 
    if (c.moveToFirst()) { 
     while (!c.isAfterLast()) { 
     List<Object> record = new ArrayList<Object>(); 
     record.add(c.getInt(0)); 
     record.add(c.getString(1)); 
     values1.add(record); 
     c.moveToNext(); 
     } 
    } 
    c.close(); 

    query = "SELECT * FROM " + DatabaseConstants.RECORDS_TABLE; 
    c = database.rawQuery(query, null); 
    List<List<Object>> values2 = new ArrayList<List<Object>>(); 
    if (c.moveToFirst()) { 
     while (!c.isAfterLast()) { 
     List<Object> record = new ArrayList<Object>(); 
     record.add(c.getInt(0)); 
     record.add(c.getInt(1)); 
     record.add(c.getInt(2)); 
     record.add(c.getInt(3)); 
     values2.add(record); 
     c.moveToNext(); 
     } 
    } 
    c.close(); 

    // Copy empty database with new schema 
    copyDatabase(); 

    // Restore all old data 
    for (List<Object> record : values1) { 
     ContentValues cv = new ContentValues(); 
     cv.put(DatabaseConstants.ID_COLUMN_NAME, (Integer) record.get(0)); 
     cv.put(DatabaseConstants.USERNAME_COLUMN_NAME, record.get(1).toString()); 
     database.insert(DatabaseConstants.USERS_TABLE, null, cv); 
    } 
    for (List<Object> record : values2) { 
     ContentValues cv = new ContentValues(); 
     cv.put(DatabaseConstants.USER_ID_COLUMN_NAME, (Integer) record.get(0)); 
     cv.put(DatabaseConstants.GAME_TYPE_COLUMN_NAME, GameType.CLASSIC.name()); 
     cv.put(DatabaseConstants.WINS_COLUMN_NAME, (Integer) record.get(1)); 
     cv.put(DatabaseConstants.LOSSES_COLUMN_NAME, (Integer) record.get(2)); 
     cv.put(DatabaseConstants.TIES_COLUMN_NAME, (Integer) record.get(3)); 
     database.insert(DatabaseConstants.RECORDS_TABLE, null, cv); 
    } 
    } 

यहां डेटाबेस फ़ाइल की प्रतिलिपि बनाने के लिए कोड है। डेटाबेस प्रारंभ में खाली है, और मैंने इसे अपने ऐप के बाहर बनाया है। (मैं एक कार्यक्रम SQLite के लिए Navicat बुलाया करते थे।)

public DatabaseHelper(Context context) { 
    super(context, DatabaseConstants.DATABASE_NAME, null, 1); 
    this.context = context; 
    databasePath = context.getDatabasePath(DatabaseConstants.DATABASE_NAME).getPath(); 
    } 

    void copyDatabase() throws IOException { 
    InputStream is = context.getAssets().open(DatabaseConstants.DATABASE_NAME); // data.db 
    OutputStream os = new FileOutputStream(databasePath); 

    byte[] buffer = new byte[1024]; 
    int length; 
    while ((length = is.read(buffer)) > 0) { 
     os.write(buffer, 0, length); 
    } 

    // Close the streams. 
    os.flush(); 
    os.close(); 
    is.close(); 
    } 
1

निम्नलिखित की तरह कुछ मामलों के विशाल बहुमत के लिए आसान नहीं होगा? इस पर थोड़ा अधिक के लिए

private static final String DATABASE_ALTER_TEAM_1 = "ALTER TABLE " 
    + TABLE_TEAM + " ADD COLUMN " + COLUMN_COACH + " string;"; 

private static final String DATABASE_ALTER_TEAM_2 = "ALTER TABLE " 
    + TABLE_TEAM + " ADD COLUMN " + COLUMN_STADIUM + " string;"; 

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    if (oldVersion < 2) { 
     db.execSQL(DATABASE_ALTER_TEAM_1); 
    } 
    if (oldVersion < 3) { 
     db.execSQL(DATABASE_ALTER_TEAM_2); 
    } 
} 

, इस blog की जाँच: बस प्रत्येक संस्करण के उन्नयन के लिए नए स्तंभ जोड़ें।

संबंधित मुद्दे