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

@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

@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

@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

// 因为我们无法预知未来版本的表结构,向下兼容时最稳妥的方法就是将该版本自己需要的表重构一次
@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); // 建表
}

转自:http://pedant.cn/2014/08/01/sqliteopenhelper-onupgrade-ondowngrade-handle/
相关文章
|
11天前
|
存储 关系型数据库 数据库
高性能云盘:一文解析RDS数据库存储架构升级
性能、成本、弹性,是客户实际使用数据库过程中关注的三个重要方面。RDS业界率先推出的高性能云盘(原通用云盘),是PaaS层和IaaS层的深度融合的技术最佳实践,通过使用不同的存储介质,为客户提供同时满足低成本、低延迟、高持久性的体验。
|
19天前
|
安全 Linux 开发工具
【Azure Function】分享把Function App从.NET 6.0升级到.NET 8.0 Isolated的步骤
本文介绍了将Azure Function App从.NET 6.0升级到.NET 8.0 Isolated的步骤。.NET 6.0作为长期支持版本,生命周期至2024年11月结束。为确保持续支持,建议升级至更新版本。升级步骤包括安装.NET 8 SDK、更新Azure Functions Core Tools、修改项目文件目标框架为net8.0、更新兼容的NuGet包、本地测试以及重新发布到Azure。更多详细信息可参考官方文档。
|
2月前
|
SQL 数据库连接 数据库
在C++的QT框架中实现SQLite数据库的连接与操作
以上就是在C++的QT框架中实现SQLite数据库的连接与操作的基本步骤。这些步骤包括创建数据库连接、执行SQL命令、处理查询结果和关闭数据库连接。在实际使用中,你可能需要根据具体的需求来修改这些代码。
184 14
|
4月前
|
应用服务中间件 Linux nginx
【Azure App Service】基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?
基于Linux创建的App Service是否可以主动升级内置的Nginx版本呢?Web App Linux 默认使用的 Nginx 版本是由平台预定义的,无法更改这个版本。
171 77
|
3月前
|
数据库
【YashanDB知识库】数据库升级后用yasboot在线扩充备节点出现报错
本文来自YashanDB官网,讨论从22.2.4.1升级至23.2.2.100过程中遇到的在线扩容问题。使用yasboot增加备节点时出现“no replication addr in node 1-1”错误,尽管数据库中存在相关配置。原因是早期托管功能未支持扩容,导致OM无法获取新库配置。提供两种规避方法:一是手动修改`cod_domor.db`信息并调整配置文件;二是手动安装YashanDB并配置备机。最终已向研发反馈,将在扩容时优化配置检查逻辑。
|
2月前
|
人工智能 关系型数据库 分布式数据库
让数据与AI贴得更近,阿里云瑶池数据库系列产品焕新升级
4月9日阿里云AI势能大会上,阿里云瑶池数据库发布重磅新品及一系列产品能力升级。「推理加速服务」Tair KVCache全新上线,实现KVCache动态分层存储,显著提高内存资源利用率,为大模型推理降本提速。
|
4月前
|
SQL 弹性计算 安全
【上云基础系列04】基于标准架构的数据库升级
本文回顾了业务上云从基础到进阶的理念,涵盖基础版和全栈版架构。在“入门级:上云标准弹性架构基础版”的基础上,本文针对数据库升级,重点介绍了高可用数据库架构的升级方案,确保数据安全和业务连续性。最后,附有详细的“上云标准弹性架构”演进说明,帮助用户选择合适的架构方案。
|
5月前
|
数据管理 数据库 数据安全/隐私保护
Django—同一项目不同app使用不同数据库
在Django项目中实现不同app使用不同数据库的配置,可以通过配置多数据库、创建数据库路由和配置路由来实现。通过这种方法,可以有效地将数据隔离到不同的数据库,提高数据管理的灵活性和系统的可扩展性。希望本文能为开发者在Django项目中使用多数据库提供清晰的指导。
77 4

热门文章

最新文章