Android之数据库升级onUpgrade降级onDowngrade
借用API文档解释:
public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
当数据库需要升级时,会调用这个方法。应该使用这个方法来实现删除表、添加表或者做一些需要升级新的策略版本的事情。
SQLite ALTER TABLE的文档可以在以下网址中找到:
http://sqlite.org/lang_altertable.html
如果要给表添加一个新列,那么使用使用ALTER TABLE能够把新列插入到表中。如果要重命名或删除列,那么你能够使用ALTER TABLE能够重命名旧表,然后,创建一个新表,并把旧表中内容复制到新表中。
这个方法是事务中执行的,如果有异常被抛出,所有的改变都会被自动的回滚。
参数:
db:指定要降级的数据库
oldVersion:旧的数据库版本
newVersion:新的数据库版本
总结:
v1.0
1.没有安装过 onCreate()
--------------------------------------
v2.0 [onUpgrade 情况:n-1,onCreate 情况:1]
1.v1.0 --> v2.0 onUpgrade
2.没有安装过 onCreate()
-----------------------------------------
v3.0 [onUpgrade 情况:n-1,onCreate 情况:1]
1. v1.0 -->v3.0 onUpgrade
alter table t_message add column isdel bit default 0;
插入数据
* 2. v2.0 -->v3.0 onUpgrade
alter table t_message add column isdel bit default 0;
3. 没有安装过 onCreate()
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)
当数据库需要被降级时,调用这个方法。这个方法与onUpgrade(SQLiteDatabase, int, int)方法非常相似,但是它是在当前版本比请求的版本新的时候,才会被调用。但是这个方法不是抽象的,因此它不是强制要求客户实现它的。如果这个方法没有被重写,默认的实现会拒绝降级处理,并抛出SQLiteException异常。
这个方法是在事务中执行的。如果有异常被抛出,所有的改变都会被回滚。
参数:
db:指定要降级的数据库
oldVersion:旧的数据库版本
newVersion:新的数据库版本
总结:
降级的设计关键点
1、考虑云端要保存用户【自定义数据、行为习惯】。专业术语profile-->>提高用户黏度
2、考虑[当前]的最低版本要求-->>降低维护成本
3、尽可能本地的数据转移(所有新版本,都不删除字段)-->尽可能把未知变已知
try catch
下面是老师上课的案例:
1 package com.example.winxin2; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteDatabase.CursorFactory; 6 import android.database.sqlite.SQLiteOpenHelper; 7 import android.util.Log; 8 9 public class MyDatabaseOpenHelper extends SQLiteOpenHelper { 10 11 private static final String DB_NAME = "mydata.db"; // 数据库名称 12 private static final int version = 2; // 数据库版本 13 14 public MyDatabaseOpenHelper(Context context) { 15 super(context, DB_NAME, null, version); 16 } 17 18 // 问题:什么时候执行 19 // 没有前生 20 @Override 21 public void onCreate(SQLiteDatabase db) { 22 // TODO Auto-generated method stub 23 // 编写【从0开始到最新状态】建表语句 24 Log.i("hi", "没有数据库,创建数据库,创建v2.0成功"); 25 String sql_message = "create table t_message (id int primary key,tou1 varchar(50),userName varchar(50),lastMessage varchar(50),datetime varchar(50))"; 26 String sql_init_1 = "insert into t_message values (1,'abc','abc1','abcd1','hi1')"; 27 String sql_init_2 = "insert into t_message values (2,'abc','abc2','abcd2','hi1')"; 28 String sql_init_3 = "insert into t_message values (3,'abc','abc2','abcd2','hi1')"; 29 db.execSQL(sql_message); 30 db.execSQL(sql_init_1); 31 db.execSQL(sql_init_2); 32 db.execSQL(sql_init_3); 33 34 } 35 36 // v2.0 现在进行时 37 @Override 38 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 39 if (oldVersion == 2){ 40 String sql_upgrade_1 = "alter table t_message add column isdel bit default 0"; 41 db.execSQL(sql_upgrade_1); 42 Log.i("db", "从2到3,升级成功!"); 43 } 44 45 if (oldVersion == 1) { 46 String sql_upgrade_1 = "alter table t_message add column isdel bit default 0"; 47 db.execSQL(sql_upgrade_1); 48 String sql_init_1 = "insert into t_message values (1,'abc','abc1','abcd1','hi1',0)"; 49 String sql_init_2 = "insert into t_message values (2,'abc','abc2','abcd2','hi1',0)"; 50 String sql_init_3 = "insert into t_message values (3,'abc','abc2','abcd2','hi1',0)"; 51 db.execSQL(sql_init_1); 52 db.execSQL(sql_init_2); 53 db.execSQL(sql_init_3); 54 Log.i("db", "从1到3,升级成功!"); 55 } 56 } 57 58 /* 模拟从3.0 降低会2.0 */ 59 @Override 60 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 61 //正常来讲大于2.0的,应该有t_message 这张表,且2.0有的字段,3.0都有 62 try { 63 //第一、先把t_message 未来的表,改名 64 String rename_sql = "alter table t_message rename to t_message_bak"; 65 db.execSQL(rename_sql); 66 Log.i("down", "1.改名成功"); 67 //第二、建立2.0的表结构 68 String sql_message = "create table t_message (id int primary key,tou1 varchar(50),userName varchar(50),lastMessage varchar(50),datetime varchar(50))"; 69 db.execSQL(sql_message); 70 Log.i("down", "2.建立2.0表结构成功"); 71 //第三、把备份的数据,copy到 新建的2.0的表 72 String sql_copy = "insert into t_message select id,tou1,userName,lastMessage,datetime from t_message_bak"; 73 db.execSQL(sql_copy); 74 Log.i("down", "3.copy到用户数据到 2.0的表"); 75 //第四、把备份表drop掉 76 String drop_sql = "drop table if exists t_message_bak"; 77 db.execSQL(drop_sql); 78 Log.i("down", "4.把备份表drop掉"); 79 80 } catch (Exception e) { 81 //失败 82 Log.i("hi", "降级失败,重新建立"); 83 String sql_drop_old_table = "drop table if exists t_message"; 84 String sql_message = "create table t_message (id int primary key,tou1 varchar(50),userName varchar(50),lastMessage varchar(50),datetime varchar(50))"; 85 String sql_init_1 = "insert into t_message values (1,'abc','abc1','abcd1','hi1')"; 86 String sql_init_2 = "insert into t_message values (2,'abc','abc2','abcd2','hi1')"; 87 String sql_init_3 = "insert into t_message values (3,'abc','abc2','abcd2','hi1')"; 88 db.execSQL(sql_drop_old_table); 89 db.execSQL(sql_message); 90 db.execSQL(sql_init_1); 91 db.execSQL(sql_init_2); 92 db.execSQL(sql_init_3); 93 } 94 } 95 96 }
我自己总结了一下:
1、创建一个继承SQLiteOpenHelper 的类,实现未实现的方法
2、里面方法采用回调函数,当触发时,系统会自动调用,不用我们手动调
3、onCreate()方法写最新版本的数据库创建和初始化
4、onUpgrade()方法写版本更新时数据库更新代码(考虑新客户和老客户,如果太久远的版本可以直接放弃维护,直接弹框要求用户更新最新版本)
5、onDowngrade()方法注意需要保存关键数据,和try catch
还有很多的不懂,如发现有错,留言告诉我,大家互相学习