美文网首页
fmdb数据库升级

fmdb数据库升级

作者: 琳琅满目浪迹天涯 | 来源:发表于2022-07-24 16:30 被阅读0次

一、数据库升级
背景:在老版本上开发的应用程序并未做数据库升级操作,以至于发布版本时候无法合并安装需要卸载重新安装
本次使用数据库: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
    }
}

相关文章

网友评论

      本文标题:fmdb数据库升级

      本文链接:https://www.haomeiwen.com/subject/emngirtx.html