一、数据库升级
背景:在老版本上开发的应用程序并未做数据库升级操作,以至于发布版本时候无法合并安装需要卸载重新安装
本次使用数据库:fmdb
升级要求:覆盖安装可升级安装
升级方式:
1、FMDB的数据迁移用FMDBMigrationManager这个工具类,FMDBMigrationManager 是与FMDB结合使用的一个第三方类库,可以记录数据库版本号并对数据库进行数据库升级等操作。不过这个库已经被作者删除
参考文章: https://www.jianshu.com/p/66bc680c4360
2、自己实现升级管理
上述两种数据库的升级方式都需要自己写sql语句。这就意味着,你需要熟练使用sql命令。
本次说第二种自己实现升级操作
先定义2个协议:返回客户端版本号和升级数据库方法
// 版本号协议
@objc protocol DatabaseVersionProtocol {
// 客户端版本号
static func clientVersion() -> String
}
@objc protocol FMDBDatabaseVersionProtocol: DatabaseVersionProtocol {
/// 开始更新数据库
static func startUpgrade(dataBase: FMDatabase) -> Error?
}
升级代码
@objc static func upgradeDatabase(db: FMDatabase? = nil, error: Error?) -> Bool {
print("============数据库地址:\(String(describing: SQLitePath()))==============")
// bk_db_version 表控制那些需要升级的版本号
var res = true
if db == nil {
DatabaseQueue.shared?.inDatabase({ db in
res = update(db: db)
})
} else {
res = update(db: db!)
}
return res
}
static func update(db: FMDatabase) -> Bool {
// 1、先判断bk_db_version表是否存在
do {
try db.executeUpdate("create table if not exists bk_db_version (version integer not null default 0)", values: nil)
} catch {
return false
}
// 开始升级
let currentVersion: Int = Int(db.intForQuery(sql: "select max(version) from bk_db_version", nil) ?? 0)
if currentVersion >= highFMDBVersion() {
return true
}
for index in currentVersion...self.highFMDBVersion() {
// 需要升级的类名
let className: AnyClass? = classFromString(className: "DatabaseVersion\(index)")
if className == nil {
continue
}
// let con = className?.conforms(to: FMDBDatabaseVersionProtocol.self)
let con = className is FMDBDatabaseVersionProtocol
if con != true {
continue
}
db.beginTransaction()
if className?.startUpgrade(dataBase: db) != nil {
// 数据库升级失败
print("数据库升级失败 version:\(String(describing: className?.clientVersion())) ")
db.rollback() // 回退
return false
}
// 更新bk_db_version表中的版本号
do {
try db.executeUpdate("insert into bk_db_version (version) values (\(index))", values: nil)
} catch {
print("数据库升级失败 version:\(String(describing: className?.clientVersion())) ")
db.rollback()
return false
}
db.commit()
}
return true
}
如有1,2,3,4个版本需要升级则创建4个升级类,在类中定义每个数据库升级版本需要如何升级,如下:
extension DatabaseVersion2: FMDBDatabaseVersionProtocol {
static func startUpgrade(dataBase: FMDatabase) -> Error? {
return creatOrUpdateTables(db: dataBase)
}
static func clientVersion() -> String {
"unknown"
}
static func creatOrUpdateTables(db: FMDatabase) -> Error? {
do {
// bk_user增加字段
if db.columnExists("cemail", inTableWithName: "bk_user") == false {
try db.executeUpdate("alter table bk_user add cemail text", values: nil)
}
} catch {
let error = db.lastError()
return error
}
return nil
}
}
网友评论