App版本更新时对SQLite数据库升级或者降级遇到的问题

SQLite是Android内置的一个很小的关系型数据库。SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类。我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定义操作。下面两个方法必须重写:

  • public void onCreate(SQLiteDatabase db)
  • public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

另外SQLiteOpenHelper子类在构造实例时必须指定当前数据库的名称(name)、版本号(version)。而这里名称就决定了数据库存储时的文件名称,而这里的版本号与App在AndroidMainfest.xml定义的versionCode没有绝对关联。也就是在App更新时如果数据库的数据结构没有发生变化那么数据库的版本号则不用增加。

onCreate:调用时机是用户首次安装应用后启动,或是清除App数据库文件后启动。这时可以在这个函数中完成初始的数据表的创建。

onUpgrade:调用时机是用户在做应用更新,覆盖安装后启动,如果新版本中数据库版本号要比旧版本中的数据库版本号高则会调用。这时可以在这个函数完成数据库版本升级带来的旧版本的兼容问题,以及数据迁移问题。

还有一个一般情况下不需要重写,但在应用出现逆向降级(如应用由版本号4降级安装版本号为3的包)时必须重写的方法onDowngrade,如果应用降级覆盖安装时没有重写该方法则会崩溃。

在数据库版本升级时, 我们可能会遇到这样一些情况:

  • 需要扩展一个表的字段
  • 删除掉原来表上某个冗余的字段
  • 新建一个表

而处理上面这些问题都要在不损害旧数据库历史数据的前提下完成。这里我们假设用户手机上之前安装的是数据库版本为1的包,升级安装的是数据库版本号为2的包。这时我们要在数据库版本为2的包在去处理这些升级逻辑。

首先是扩展一个表的字段在onUpgrade中的实现为:

MyDBHelper.java


1

2

3

4

5

6

7


@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//旧数据库版本为1,才为表pedant添加一个student_name字段

if(oldVersion < 2) {

db.execSQL("ALTER TABLE pedant ADD COLUMN student_name text");

}

}

SQLite对ALTER TABLE的支持是有限的,你可以在一个存在表上添加一个字段到末尾,或者是改变表的名称。但如果你想做更复杂的操作,比如删除一个表已有的字段,就要重新创建这个表并完成数据迁移,而不能使用DROP COLUMN这样方便的命令了。详见SQLite Frequently Questions

比如表pedant原来有三个字段a、b、c,现在想删除c字段,那么在onUpgrade中写法如下:

MyDBHelper.java


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18


@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//旧数据库版本为1,删除表pedant的c字段

if(oldVersion < 2) {

db.beginTransaction();

try {

db.execSQL("CREATE TEMPORARY TABLE pe_backup (a, b);");

db.execSQL("INSERT INTO pe_backup SELECT a, b FROM pedant;");

db.execSQL("DROP TABLE pedant;");

db.execSQL("CREATE TABLE pedant(a text, b text);");

db.execSQL("INSERT INTO pedant SELECT a, b FROM pe_backup;");

db.execSQL("DROP TABLE pe_backup;");

db.setTransactionSuccessful();

} finally {

db.endTransaction();

}

}

}

这样就既完成了对c字段的删除也保留了原来表上的数据。

最后一种情况最简单直接执行CREATE语句就要可以了。

MyDBHelper.java


1

2

3

4

5

6

7


@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

//旧数据库版本为1,创建新表newtb

if(oldVersion < 2) {

db.execSQL("CREATE TABLE newtb(a text, b text);");

}

}

数据库在做升级时我们能明确地知道当前我们要对各旧表进行什么样的操作来兼容新版本。但如果在数据库降级时,情况就不一样了,针对我们开发新版本2时, 我们不能明确地知道以后的新版本比如版本3、4的数据库结构走向是怎样的。比如以后用户从版本3回退到我们正在开发的版本2,由于我们开发当时不能预知版本3的表结构,不知版本3的数据表能否兼容到版本2(假如版本3升级时删除了一个版本2一直在用的表字段,这时回退数据结构可能就不兼容了),那么我们在开发版本2时最稳妥的做法是重写onDowngrade时把所有当前版本将用到的表全部重建,即降级时扔掉以前全部的数据

MyDBHelper.java


1

2

3

4

5

6

7

8

9

10


// 因为我们无法预知未来版本的表结构,向下兼容时最稳妥的方法就是将该版本自己需要的表重构一次

@Override

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

db.execSQL("DROP TABLE IF EXISTS t1;");

db.execSQL("DROP TABLE IF EXISTS t2;");

db.execSQL("DROP TABLE IF EXISTS t3;");

db.execSQL("DROP TABLE IF EXISTS t4;");

....

onCreate(db); // 建表

}

欢迎转载,请注明出处链接!!!

时间: 2024-10-09 04:44:39

App版本更新时对SQLite数据库升级或者降级遇到的问题的相关文章

Android版本更新时对SQLite数据库升级或者降级遇到的问题

SQLite是Android内置的一个很小的关系型数据库.SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类.我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定义操作.下面两个方法必须重写: public void onCreate(SQLiteDatabase db) public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 另外SQLiteOpenHelper子类在

android sqlite数据库升级

public class DataHelper extends SQLiteOpenHelper{ private static final int version=1; public DataHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version);//version代表数据库版本号码 // TODO Auto-generat

Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())

数据库版本升级对软件的管理操作. 我们手机经常会收到xxx软件升级什么的提醒,你的软件版本更新,同时你的数据库对应的版本也要相应的更新. 数据库版本更新需要主要的问题: 软件的1.0版本升级到1.1版本时,老的数据不能丢. 那么在1.1版本的程序中就要有地方能够检测出来新的软件版本与老的数据库不兼容,并且能够有办法把1.0软件的数据库升级到1.1软件能够使用的数据库. 换句话说,要在1.0软件的数据库的那个表中增加那个字段,并赋予这个字段默认值. 当然有的时候我们对更新后的 版本并没有什么好感,

Android数据库升级、降级、创建(onCreate() onUpgrade() onDowngrade())的注意点

以下内容可以作为面试官在面试的时候的问题,感觉比较好,是比较常用的知识点,可以用来考察基础是否扎实. 也可以程序猿学习.开发中的注意点.因为稍微不注意,就有可能导致数据库不能用. DBAdapter.java是一个简单的类,主要用来进行数据库操作. 1 package com.example.test_20131218; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 6

android sqlite 数据库升级

场景: 数据库版本v1            有一个persion表 数据库版本v2             新增表student 数据库版本v3             persion表新增一个字段 1 package com.example.natedb; 2 3 import android.content.Context; 4 import android.database.SQLException; 5 import android.database.sqlite.SQLiteData

用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级

目录 目录 前文列表 扩展阅读 Alembic 查看指令 manager db 的可用选项 初始化 DB Migrate 开始第一次跟踪 将记录文件应用到数据库中实时升级数据库结构 回滚到某一个记录环境中 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 Flask 来写个轻博客 (3) - (M)VC_连接 MySQL 和 SQLAlchemy 用 Flask 来写个轻博客 (4) - (M)VC_创建数据模型

Android中SQLite数据库小计

2016-03-16 Android数据库支持 本文节选并翻译<Enterprise Android - Programing Android Database Applications for the Enterprise>.学习目标: 学习Android对SQL的支持. 理解在Java中使用SQL——通过SQLiteDatabase类. 创建数据库——SQLiteOpenHelper类. 理解loaders.cursors和adapters. 为了在程序中使用本地的,结构化的数据,需要完成

Android中多表的SQLite数据库(译)

原文: Android SQLite Database with Multiple Tables 在上一篇教程Android SQLite Database Tutorial中,解释了如何在你的Android应用中使用SQLite数据库.但它只涵盖了你的数据库中只有一个表的情景.有很多人询问当数据库中有多个表时如何处理. 以下解释了当有多个表存在时如何处理SQLite数据库. 用例: Todo应用 为了便于理解,我在这一教程中用了一个真实的用例,一个TODO应用的数据库方案.本文不会涵盖如何设计

Android Sqlite 数据库版本更新

http://87426628.blog.163.com/blog/static/6069361820131069485844/ 1.自己写一个类继承自SqliteOpenHelper 2.会实现SqliteOpenHelper的两个方法 onCreate与onUpgrade,google文档对两个回调方法的解释是创建数据库的时候调用与更新数据库的版本的时候调用 3.Sqlite数据库主要是用来缓存应用的数据,而应用却是一直在更新版本,相应的数据的表的字段也会一直增加会改变或减少 4.这个时候就