androidでSQLiteを利用する際には、SQLiteOpenHelperクラスを継承してテーブルのCreateやUpdateを行うと思いますが、アップデートによってテーブルカラムを増やしたりしたい場合、前のテーブルデータを引継ぎながら新しいテーブルに置き換える実装を紹介します。
以下コードです。
public class ListDataOpenHelper extends SQLiteOpenHelper {
public ListDataOpenHelper(Context context) {
super(context, "ComicMemoDB", null, 2);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table comicdata("
+ "id long not null,"
+ "title text default '',"
+ "author text default '',"
+ "number text default '1',"
+ "memo text default '',"
+ "inputdate text default '',"
+ "status long default 0"
+ ");");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
final String targetTable = "comicdata";
db.beginTransaction();
try {
// 元カラム一覧
db.execSQL("ALTER TABLE " + targetTable + " RENAME TO temp_" + targetTable);
final List columns = getColumns(db, "temp_" + targetTable);
onCreate(db);
// 新カラム一覧
final List newColumns = getColumns(db, targetTable);
// 変化しないカラムのみ抽出
columns.retainAll(newColumns);
// 共通データを移す。(OLDにしか存在しないものは捨てられ, NEWにしか存在しないものはNULLになる)
final String cols = join(columns, ",");
db.execSQL(String.format(
"INSERT INTO %s (%s) SELECT %s from temp_%s", targetTable,
cols, cols, targetTable));
// 終了処理
db.execSQL("DROP TABLE temp_" + targetTable);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
private static List getColumns(SQLiteDatabase db, String tableName) {
List ar = null;
Cursor c = null;
try {
c = db.rawQuery("SELECT * FROM " + tableName + " LIMIT 1", null);
if (c != null) {
ar = new ArrayList(Arrays.asList(c.getColumnNames()));
}
} finally {
if (c != null)
c.close();
}
return ar;
}
private static String join(List list, String delim) {
final StringBuilder buf = new StringBuilder();
final 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();
}
}
基本的には、「SQLiteOpenHelper でテーブルカラム変更時にデータを引き継ぐ」の記事を参考にさせていただいたのですが、一部変更点として、
// 元カラム一覧
db.execSQL("ALTER TABLE " + targetTable + " RENAME TO temp_" + targetTable);
final List columns = getColumns(db, "temp_" + targetTable);
onCreate(db);
// 新カラム一覧
final List newColumns = getColumns(db, targetTable);
この部分です。
onCreate(ComicMemoDB旧テーブル作成)
→onUpgrade(temp_ComicMemoDBにリネーム)
→getColumns(旧テーブルカラム取得)
→oncreate(ComicMemoDB新テーブル作成)
→getColumns(新テーブルカラム取得)
元の記事のように旧テーブルのカラムリストを取得してからリネームだと上手くいかなかったため、先にリネームを行ってから旧テーブルのカラムリストを取得するように修正しました。
以下のアプリで利用しています。