web-dev-qa-db-ja.com

Android SQLiteデータベース、なぜテーブルを削除してアップグレード時に再作成するのか

私がフォローしているチュートリアルでは、これを見る多くの場所で、onUpgrade->テーブルが存在する場合はドロップし、テーブルを再作成します。

これの目的は何ですか?

private static class DbHelper extends SQLiteOpenHelper{

    public DbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
                KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
                KEY_NAME + " TEXT NOT NULL, " +
                KEY_HOTNESS + " TEXT NOT NULL);"
        );  
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
        onCreate(db);
    }       
}
28
Esqarrouth

アップグレード時には、列を追加するか、データベースにテーブルを追加する必要があることに同意します。なぜこのデータをすべて削除してからテーブルを再作成するのですか?このブログエントリを見つけましたAdams Incremental Update Method。また、ユーザーが各リリースでアプリをアップグレードしなかった場合の状況も処理します。

ドロップテーブルを行わないsqlite onupgradeの良いブログです

32
danny117

まあ、Androidアプリケーションで最も一般的な方法は、データベースのアップグレードが正常に行われたときにユーザーを「再ログ」することです。また、ローカルデータベースはあるバージョンから別のバージョンへの移行を慎重に計画するよりも、データベースを削除して再作成し、サーバーから再入力する方がはるかに簡単です。

確かにbestのアプローチではありませんが、簡単です。

移行(古いバージョンのデータベースから新しいバージョンへの変更)の実装方法の例を作成するには

DbHelperクラスで、データベースがバージョン1であることを定義するとしましょう。アプリケーションの新しいバージョン(バージョン2)では、テーブルの1つにさらにいくつかの列が必要です。

したがって、テーブルをアップグレードし、ALTER TABLE {tableName} ADD COLUMN COLNew {type}を使用して列を追加する必要があります。

このリンクを確認してください-> sqliteのテーブルに新しい列を挿入しますか?

onUpgrade()メソッドは、以下を追加してその変更を反映する必要があります。

 @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    switch(oldVersion){
        case 1:
            db.execSQL("ALTER TABLE " + DATABASE_TABLE + " ADD COLUMN " + NEW_COLUMN_NAME + TYPE);
    }
}  
32
Aedis

作成するアプローチの種類とデータの重要性、テーブルの複雑さによって異なります。例:アプリがかなり頻繁にアップグレードされ、テーブル構造に十分な時間が変更されている場合、このアプローチでは、dbのすべてのバージョンの構造を変更するコードを記述するよりも、テーブルを削除して再作成する方が良いサーバー側にあるデータをバックアップできることを確認する必要があります。

私の経験から:将来さらに変更があるかもしれないと判断できれば、再作成はより良いです。

3
viv

きれいなスタートです。メソッドonCreateには現在有効なデータベース構造があります。アプリをインストールするユーザーがこのメソッドを実行します。アップグレードするユーザーの場合、onUpgradeメソッドが実行され、DROP TABLE IF EXISTはクリーンスタートです(古いテーブルと新しいテーブルの構造が異なる場合に備えて)-ドロップし、onCreateメソッドで再作成します。お役に立てれば! :)

2
MSquare

テーブルデータを保持する場合は、CSVファイルにダンプし、テーブルの作成後に挿入して戻すことができます。 (データをサーバーにダンプする必要はありません)データをダンプするためのサンプルコードを次に示します。ファイル名をテーブル名に設定できます。カーソルはgetAllステートメントから作成されます

public boolean createCsvSaveToFile(Cursor cursor, String fileName) throws IOException {
    String csv = "";
    int colunmCount = cursor.getColumnCount();
    /* check if extarnal drive is readerble */
    if (!isExternalStorageWritable()) {
        fileError = "can not save to external storage";
        fileinfo = "Please mount your SD card";
        return false;
    } else {
        /* create the CSV */
        for (int i = 0; i < colunmCount; i++) {
            csv += QUOTES + cursor.getColumnName(i).toString() + QUOTES + INNER_DELIMITER;
        }
        csv = csv.replaceAll(",$", "");
        csv += LINE_END;
        if (cursor.moveToFirst()) {
            do {
                for (int i = 0; i < colunmCount; i++) {//GET COLUNM values
                    csv += QUOTES + cursor.getString(i) + QUOTES + INNER_DELIMITER;
                }
                csv = csv.replaceAll(",$", "");
                csv += LINE_END;
            } while (cursor.moveToNext());
        }
        /* save file */
        File file = getDataDir(fileName);
        FileOutputStream out = new FileOutputStream(file);
        out.write(csv.getBytes());
        out.flush();
        out.close();
        return true;
    }
}

データを挿入するためのサンプルコードを次に示します。 CSVファイル名がテーブル名と同じであると仮定する

private void readFromFile(SQLiteDatabase database, File file) {
    boolean hasColunms = false;
    String tableName = file.getName().replaceAll(".csv$", "");
    String sql;
    String colunmNames = "";
    String colunmValues;
    try {
        BufferedReader br = new BufferedReader(new FileReader(file));
        String line;
        while ((line = br.readLine()) != null) {
            if (!hasColunms ) {
                /* get column names */
                line = line.replaceAll("\"", "");
                colunmNames = line;
                hasColunms = true;
            } else {
                line = line.replaceAll("\"", "'");
                colunmValues = line;
                sql = "INSERT INTO " + tableName + " (" + colunmNames + ") VALUES (" + colunmValues + ")";
                database.execSQL(sql);
            }
        }
        br.close();
    } catch (IOException e) {
        database.close();
        /* You may need to add proper error handling here
    }

多くのcsvファイルをループするには、次のコードを使用できます

public boolean csvTodatabase(SQLiteDatabase database) {
    FileStuff f = new FileStuff();
    File time;
    /* check if extarnal drive is readerble */
    if (!f.isExternalStorageReadable()) {
        f.fileError = "can not read external storage";
        f.fileinfo = "Please remount your SD card";
        return false;
    } else {
        /* get all files from extarnal drive data */
        ArrayList<File> files = new ArrayList<File>();
        File directory = new File(FileStuff.DATA_DIRECTORY);
        if (!directory.exists()) {
            return false;
        }
        File[] fList = directory.listFiles();
        for (File file : fList) {
            if (file.isFile()) {
                files.add(file);
            }
        }  
        for (File csvfile : files) {
            readFromFile(database, csvfile);
        }
        return true;
    }
}

注:readFromFile(database、csvfile);前の関数です

0
hyena