2011-11-15 12 views
103

मैंने पहले से ही अपने ऐप के लिए स्क्लाइट टेबल बनाए हैं, लेकिन अब मैं डेटाबेस में एक नई टेबल जोड़ना चाहता हूं।एंड्रॉइड: डीबी संस्करण को अपग्रेड करना और नई तालिका

मैं मेज

private static final String DATABASE_CREATE_color = 
    "CREATE TABLE IF NOT EXISTS files(color text, incident_id text)"; 

onCreate और नीचे के रूप में onUpgrade बनाने के लिए

private static final int DATABASE_VERSION = 2; 

और जोड़ा गया स्ट्रिंग नीचे के रूप में डीबी संस्करण बदल:

@Override 
    public void onCreate(SQLiteDatabase database) { 
     database.execSQL(DATABASE_CREATE_incident); 
     database.execSQL(DATABASE_CREATE_audio); 
     database.execSQL(DATABASE_CREATE_video); 
     database.execSQL(DATABASE_CREATE_image); 

    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     //drop table and add new tables when version 2 released. 
     db.execSQL(DATABASE_CREATE_color); 

    } 

लेकिन किसी कारण के लिए नई तालिका नहीं बनाई जा रही है। मैं क्या गलत कर रहा हूं?

+0

[यह] (https://stackoverflow.com/a/3424444/3681880) एक और दिलचस्प समाधान है, लेकिन अब तक का सबसे मजबूत संस्करण मैंने देखा है [यहां] (https://riggaroo.co.za/android-SQLite-डेटाबेस का उपयोग-onupgrade-सही ढंग से /)। – Suragch

उत्तर

243

1. onCreate बारे में() और onUpgrade() जब भी एप्लिकेशन हाल में स्थापित किया गया है

onCreate(..) कहा जाता है। onUpgrade को जब भी ऐप अपग्रेड और लॉन्च किया जाता है और डेटाबेस संस्करण समान नहीं होता है।

2. डाटाबेस संस्करण

आप की तरह एक निर्माता की जरूरत Incrementing:

MyOpenHelper(Context context) { 
    super(context, "dbname", null, 2); // 2 is the database version 
} 

महत्वपूर्ण: अकेले एप्लिकेशन संस्करण Incrementing पर्याप्त onUpgrade के नाम से जाना के लिए नहीं है!

3. अपने नए उपयोगकर्ताओं को न भूलें!

अपने OnCreate() विधि को

database.execSQL(DATABASE_CREATE_color); 

जोड़ने के लिए के रूप में अच्छी या नव स्थापित क्षुधा तालिका की कमी होगी मत भूलना।

4. कैसे समय

साथ इसने कई डेटाबेस परिवर्तन आप लगातार एप्लिकेशन उन्नयन है, जिनमें से कई डेटाबेस उन्नयन है से निपटने के लिए, आप oldVersion जांच सुनिश्चित होना चाहते हैं:

onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    switch(oldVersion) { 
    case 1: 
     db.execSQL(DATABASE_CREATE_color); 
     // we want both updates, so no break statement here... 
    case 2: 
     db.execSQL(DATABASE_CREATE_someothertable); 
    } 
} 

इस तरह जब कोई उपयोगकर्ता संस्करण 1 से संस्करण 3 तक अपग्रेड करता है, तो उन्हें दोनों अपडेट मिलते हैं। जब कोई उपयोगकर्ता संस्करण 2 से 3 तक अपग्रेड करता है, तो उन्हें केवल संशोधन 3 अपडेट मिलता है ... आखिरकार, जब भी आप अपडेट जारी करते हैं, तो आप अपने उपयोगकर्ता आधार के 100% पर अपग्रेड नहीं कर सकते हैं। कभी कभी वे एक अद्यतन या 12 :)

5. छोड़ नियंत्रण में संशोधन संख्या रखते हुए, जबकि

विकासशील और अंत में ... बुला

adb uninstall <yourpackagename> 

पूरी तरह से एप्लिकेशन अनइंस्टॉल। जब आप दोबारा स्थापित करते हैं, तो आपको onCreate पर हिट करने की गारंटी दी जाती है जो आपको डेटाबेस संस्करण को समताप मंडल में बढ़ाना जारी रखने से रोकती है ...

+6

'ऑनक्रेट() ' – Greyson

+4

पर कॉल जोड़ने के बारे में अच्छा बिंदु # 4 के बारे में: क्या' पुराना संस्करण 'तर्क पारित करने का बेहतर विचार नहीं होगा? यदि कोई अपग्रेड कथन दोहराया जा सकता है, तो आप उन्हें अधिकतर अद्यतित डेटाबेस पर दोहरा सकते हैं। यदि एक बयान में से एक टेबल को छोटा करना है, तो यह बहुत बुरा होगा। – Greyson

+3

@Greyson: महान बिंदु! ईमानदारी से, मैं इसके बारे में कभी भी सोचने के लिए थोड़ा मूर्ख महसूस करता हूं। कभी-कभी मुझे लगता है कि हम उन तर्कों का उपयोग करने की आदत में हैं जो हम चाहते हैं और बाकी को अनदेखा कर रहे हैं! – jkschneider

9

आपका कोड सही दिखता है। मेरा सुझाव यह है कि डेटाबेस पहले ही सोचता है कि यह अपग्रेड किया गया है। यदि आपने संस्करण संख्या को बढ़ाने के बाद प्रोजेक्ट को निष्पादित किया है, लेकिन execSQL कॉल जोड़ने से पहले, आपके टेस्ट डिवाइस/एमुलेटर पर डेटाबेस पहले से ही यह मान सकता है कि यह संस्करण 2 पर है।

यह सत्यापित करने का एक त्वरित तरीका संस्करण को बदलना होगा संख्या 3 - यदि यह उसके बाद अपग्रेड हो जाती है, तो आप जानते हैं कि यह इसलिए था क्योंकि आपका डिवाइस मानता था कि यह पहले से ही अपग्रेड किया गया था।

+1

धन्यवाद। डेटा मदद की :) 3 में बदलने के बाद यह काम किया :) –

+0

फिर, जैसा कि अपेक्षित था, आपका कोड ठीक था; बस जब यह वृद्धिशील नहीं चला था। तालिका निर्माण को 'onCreate()' में जोड़ना याद रखें जैसे jkschneider ने इंगित किया। – Greyson

2

आप SQLiteOpenHelper की onUpgrade विधि का उपयोग कर सकते हैं। ऑन अपग्रेड विधि में, आपको पुराने वर्जन को पैरामीटर में से एक के रूप में मिलता है।

onUpgradeswitch का उपयोग करें और case प्रत्येक डेटाबेस में वर्तमान संस्करण का ट्रैक रखने के लिए संस्करण संख्या का उपयोग करें।

यह सबसे अच्छा है कि आप oldVersion से newVersion के लिए खत्म हो पाश, एक समय में version 1 से incrementing और फिर कदम से कदम डेटाबेस का उन्नयन। यह बहुत उपयोगी है जब डेटाबेस संस्करण 1 वाला कोई व्यक्ति लंबे समय बाद ऐप को अपग्रेड करता है, डेटाबेस संस्करण 7 का उपयोग कर एक संस्करण में और ऐप कुछ असंगत परिवर्तनों के कारण क्रैश हो रहा है।

फिर डेटाबेस में अपडेट चरण-वार किए जाएंगे, जिसमें सभी संभावित मामलों को शामिल किया जाएगा, यानी प्रत्येक नए संस्करण के लिए किए गए डेटाबेस में किए गए परिवर्तनों को शामिल करना और इस प्रकार आपके एप्लिकेशन को क्रैश होने से रोकना।

उदाहरण के लिए:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    switch (oldVersion) { 
    case 1: 
     String sql = "ALTER TABLE " + TABLE_SECRET + " ADD COLUMN " + "name_of_column_to_be_added" + " INTEGER"; 
     db.execSQL(sql); 
     break; 

    case 2: 
     String sql = "SOME_QUERY"; 
     db.execSQL(sql); 
     break; 
    } 

} 
+0

यदि आप उन ब्रेक स्टेटमेंट को हटाते हैं तो आपको लूप –

1

@ jkschneider के जवाब सही है। हालांकि एक बेहतर दृष्टिकोण है।

लिंक https://riggaroo.co.za/android-sqlite-database-use-onupgrade-correctly/

from_1_to_2.sql

ALTER TABLE books ADD COLUMN book_rating INTEGER; 

from_2_to_3.sql

ALTER TABLE books RENAME TO book_information; 

from_3_to_4.sql

में वर्णित के रूप में प्रत्येक अद्यतन के लिए एक एसक्यूएल फ़ाइल में आवश्यक परिवर्तन लिखें
ALTER TABLE book_information ADD COLUMN calculated_pages_times_rating INTEGER; 
UPDATE book_information SET calculated_pages_times_rating = (book_pages * book_rating) ; 

ये .sql फ़ाइलों को डेटाबेस के संस्करण के अनुसार अपग्रेड() विधि में निष्पादित किया जाएगा। https://github.com/riggaroo/AndroidDatabaseUpgrades

+0

की आवश्यकता नहीं होगी, मैं बस यहां आने और एक ही सलाह लिखने वाला था। मुझे खुशी है कि आप इसे पहले ही कर चुके हैं। लोगों को निश्चित रूप से आपके द्वारा लिंक किए गए लेख को पढ़ना चाहिए। यह भी है [एंड्रॉइड SQLiteAssetHelper] (https://github.com/jgilfelt/android-sqlite-asset-helper) उन्नयन के लिए सिफारिश करता है। यह भी है [सीएल।] (Https://stackoverflow.com/users/11654/cl) (* * स्टैक ओवरफ़्लो पर * SQLite विशेषज्ञ) [अनुशंसा करता है] (https://stackoverflow.com/a/42361543/ 3,681,880)। – Suragch

0

डेटाबेस संस्करणों हैंडलिंग अनुप्रयोग विकास की बहुत ही महत्वपूर्ण हिस्सा है:

DatabaseHelper.java

public class DatabaseHelper extends SQLiteOpenHelper { 

    private static final int DATABASE_VERSION = 4; 

    private static final String DATABASE_NAME = "database.db"; 
    private static final String TAG = DatabaseHelper.class.getName(); 

    private static DatabaseHelper mInstance = null; 
    private final Context context; 

    private DatabaseHelper(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
     this.context = context; 
    } 

    public static synchronized DatabaseHelper getInstance(Context ctx) { 
     if (mInstance == null) { 
      mInstance = new DatabaseHelper(ctx.getApplicationContext()); 
     } 
     return mInstance; 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     db.execSQL(BookEntry.SQL_CREATE_BOOK_ENTRY_TABLE); 
     // The rest of your create scripts go here. 

    } 


    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     Log.e(TAG, "Updating table from " + oldVersion + " to " + newVersion); 
     // You will not need to modify this unless you need to do some android specific things. 
     // When upgrading the database, all you need to do is add a file to the assets folder and name it: 
     // from_1_to_2.sql with the version that you are upgrading to as the last version. 
     try { 
      for (int i = oldVersion; i < newVersion; ++i) { 
       String migrationName = String.format("from_%d_to_%d.sql", i, (i + 1)); 
       Log.d(TAG, "Looking for migration file: " + migrationName); 
       readAndExecuteSQLScript(db, context, migrationName); 
      } 
     } catch (Exception exception) { 
      Log.e(TAG, "Exception running upgrade script:", exception); 
     } 

    } 

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

    } 

    private void readAndExecuteSQLScript(SQLiteDatabase db, Context ctx, String fileName) { 
     if (TextUtils.isEmpty(fileName)) { 
      Log.d(TAG, "SQL script file name is empty"); 
      return; 
     } 

     Log.d(TAG, "Script found. Executing..."); 
     AssetManager assetManager = ctx.getAssets(); 
     BufferedReader reader = null; 

     try { 
      InputStream is = assetManager.open(fileName); 
      InputStreamReader isr = new InputStreamReader(is); 
      reader = new BufferedReader(isr); 
      executeSQLScript(db, reader); 
     } catch (IOException e) { 
      Log.e(TAG, "IOException:", e); 
     } finally { 
      if (reader != null) { 
       try { 
        reader.close(); 
       } catch (IOException e) { 
        Log.e(TAG, "IOException:", e); 
       } 
      } 
     } 

    } 

    private void executeSQLScript(SQLiteDatabase db, BufferedReader reader) throws IOException { 
     String line; 
     StringBuilder statement = new StringBuilder(); 
     while ((line = reader.readLine()) != null) { 
      statement.append(line); 
      statement.append("\n"); 
      if (line.endsWith(";")) { 
       db.execSQL(statement.toString()); 
       statement = new StringBuilder(); 
      } 
     } 
    } 
} 

एक उदाहरण परियोजना एक ही लिंक भी प्रदान की जाती है। मुझे लगता है कि आपके पास पहले से ही श्रेणी AppDbHelper SQLiteOpenHelper है। जब आप इसे विस्तारित करेंगे तो आपको onCreate और onUpgrade विधि लागू करने की आवश्यकता होगी।

  1. onCreate और onUpgrade तरीकों

    • onCreate जब एप्लिकेशन नव स्थापित कहा जाता है कहा जाता है।
    • onUpgrade जब ऐप अपडेट किया गया था।
  2. डेटाबेस संस्करणों को व्यवस्थित करना मैं कक्षा विधियों में संस्करणों का प्रबंधन करता हूं। इंटरफेस माइग्रेशन के कार्यान्वयन बनाएँ। जैसे पहले संस्करण के लिए MigrationV1 वर्ग बनाने के लिए, दूसरा संस्करण MigrationV1ToV2 बनाने (ये मेरे नामकरण परंपरा हैं)


    public interface Migration { 
     void run(SQLiteDatabase db);//create tables, alter tables 
    } 

उदाहरण माइग्रेशन:

public class MigrationV1ToV2 implements Migration{ 
     public void run(SQLiteDatabase db){ 
     //create new tables 
     //alter existing tables(add column, add/remove constraint) 
     //etc. 
    } 
    } 
  1. प्रवासन वर्गों का उपयोग करना

onCreate: चूंकि onCreate कॉल किया जाएगा एप्लिकेशन ताजा स्थापित है, हमें सभी माइग्रेशन (डेटाबेस संस्करण अपडेट) निष्पादित करने की भी आवश्यकता है। तो onCreate इच्छा इस तरह दिखता है:

public void onCreate(SQLiteDatabase db){ 
     Migration mV1=new MigrationV1(); 
     //put your first database schema in this class 
     mV1.run(db); 
     Migration mV1ToV2=new MigrationV1ToV2(); 
     mV1ToV2.run(db); 
     //other migration if any 
    } 

onUpgrade: जब आवेदन पहले से स्थापित है इस विधि के नाम से जाना जाएगा और यह नया आवेदन संस्करण में अपडेट है। यदि एप्लिकेशन में कोई डेटाबेस परिवर्तन होता है तो नए माइग्रेशन क्लास में सभी डेटाबेस परिवर्तन और डेटाबेस संस्करण में वृद्धि करें।

उदाहरण के लिए, मान लें कि उपयोगकर्ता ने एप्लिकेशन इंस्टॉल किया है जिसमें डेटाबेस संस्करण 1 है, और अब डेटाबेस संस्करण 2 को अपडेट किया गया है (MigrationV1ToV2 में रखे गए सभी स्कीमा अपडेट)। डेटाबेस स्कीमा के लिए onCreate

में मार डाला जाना चाहिए सभी उन्नयन ( onUpgrade में उल्लेख किया है): अब जब आवेदन के लिए उन्नत, हम इस तरह MigrationV1ToV2 में डेटाबेस स्कीमा परिवर्तनों को लागू करने से डेटाबेस अपग्रेड करने की आवश्यकता:

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    if (oldVersion < 2) { 
     //means old version is 1 
     Migration migration = new MigrationV1ToV2(); 
     migration.run(db); 
    } 
    if (oldVersion < 3) { 
     //means old version is 2 
    } 
} 

नोट

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