美文网首页
Android数据库表升级(添加列),并保留原表中的数据

Android数据库表升级(添加列),并保留原表中的数据

作者: 嘤嘤嘤999 | 来源:发表于2019-06-27 11:26 被阅读0次

步骤:

  • 1、首先第一步是更改数据库的 version,当检测到你当前版本比之前的高后会执行onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法,这个方法中第一个参数 db 就是你构造方法中的数据库对象,第二个参数 oldVersion 就是你当前数据库之前的版本,第三个参数 newVersion就是当前数据库现在要升级到的版本。在这个方法里需要对不同版本做不同的操作,假设:

      当前使用app的用户该数据库版本为 1 ,而你现在新数据库版本为 2 ,那么你需要把 1 -> 2版本之间的变化写到一起,比如你在版本更新到 2 时添加了一个列,就要把一个列插入表中。
      当前使用app的用户改数据库版本为 1 或者为 2 ,而你现在新数据库版本为 3 ,那么你需要把 1 -> 3 版本之间所有的变化写到一起,比如你在版本从 1 更新到 2 时添加了一个列,从 2 更新到 3 时添加了二个列,这个时候你就要分情况处理了,如果用户是直接从 1 升到 3 ,那么你要添加三个列,如果用户是从 2 升到 3 ,那么你要添加二个列。
    
  • 2、在 onUpgrade 中做添加字段或者删除字段的操作!!!!注意:这里有两种需求!!第一种:不需要保留原表的数据,在我现在公司项目中有一张表要修改一个列名,但是每次使用的都是新数据,所以可以直接删除原表,再重新创建表!第二种:需要保留原数据,只不过后续app的版本添加了功能需要在该表中使用新的列!这里我解决的是第二种情况,也就是需要保留原数据的情况!
    先写思路,最后贴代码,这里以 user 表为例:

      (1)将原来的表更改名字为一张临时表:  "alert table user rename to_temp_user"  ,临时表名可以自己定义,我定义的是  _temp_+原表名 ,比如原表名为 user 表,临时表名就为  _temp_user 。
      (2)创建一张新表,表名为原来的表名,注意:这里的新表中的列要有你需要添加的列,并将新的列添加的原表中的末尾:"create table if not exists user(表中列名和数据类型,多个列以,逗号隔开 )" 。
      (3)将临时表的数据复制到名字为原来表名的新表(这里有一点要注意,因为新的列是在末尾,所以这里我们要预留值给新列,如果没有预留值我也不知道会出什么问题。。。欢迎博友给出意见!!)具体的实现细节在接下来的sql语句中体现:"insert into user select *,' ' from _temp_user" ,这里select * 之后的单引号之间有空格,如果添加多个字段就添加多个' ',以逗号隔开,比如添加两个字段:"insert into user select *,' ',' ' form _temp_user",意思就是给新添加的列赋值为 ' ' !!
      (4)将临时表删除,数据已经复制完毕,有新添加列的表已经生成并保留了数据,临时表已经没用利用价值了,删吧,任性一回!!删除sql语句:"drop  table _temp_user"。
    

升级表的操作就结束了!接下来该贴出代码了:

/**
     * 在表中添加字段方法 操作步骤: 1、先更改表名 2、创建新表,表名为原来的表名 3、复制数据 4、删除旧表
     *
     * @param db
     *            数据库名
     * @param newColumnArr
     *            添加的新字段的表名数组
     * @param oldTableName
     *            旧表名,在方法内部将旧表名修改为 _temp_+oldTableName
     */
    private void addColumn(SQLiteDatabase db, String[] newColumnArr,
            String oldTableName) {
       
        if (db == null || newColumnArr == null || newColumnArr.length < 1
                || TextUtils.isEmpty(oldTableName)) {
            // 数据库为空,新字段个数为0,添加字段后的字段数组个数为0,旧表名为空
            return;
        }
 
        // 拿到旧表中所有的数据
        Cursor cursor = db.rawQuery("select * from " + oldTableName, null);
        if (cursor == null) {
            // 如果游标为空,说明旧表中没有数据,如果是这种情况那就可以直接改表的字段,不需要转移数据了,代码后面也有,省略掉复制数据的操作就好
            return;
        }
        // 拿到原来的表中所有的字段名
        String[] oldColumnNames = cursor.getColumnNames();
 
        // 更改原表名为临时表
        String tempTableName = "_temp_" + oldTableName;
        db.execSQL(
                "alter table " + oldTableName + " rename to " + tempTableName);
 
        // 创建新表
        if (oldColumnNames.length < 1) {
            // 如果原来的表中字段个数为0
            return;
        }
 
        // 创建一个线程安全的字符串缓冲对象,防止用conn多线程访问数据库时造成线程安全问题
        StringBuffer createNewTableStr = new StringBuffer();
        createNewTableStr
                .append("create table if not exists " + oldTableName + "(");
        for (int i = 0; i < oldColumnNames.length; i++) {
            if (i == 0) {
                createNewTableStr.append(oldColumnNames[i]
                        + " integer primary key autoincrement,");
            } else {
                createNewTableStr.append(oldColumnNames[i] + ",");
            }
        }
 
        for (int i = 0; i < newColumnArr.length; i++) {
            if (i == newColumnArr.length - 1) {
                // 最后一个
                createNewTableStr.append(newColumnArr[i] + ")");
            } else {
                // 不是最后一个
                createNewTableStr.append(newColumnArr[i] + ",");
            }
        }
      
        db.execSQL(createNewTableStr.toString());
 
        // 复制旧表数据到新表
        StringBuffer copySQLStr = new StringBuffer();
        copySQLStr.append("insert into " + oldTableName + " select *,");
        // 有多少个新的字段,就要预留多少个' '空值给新字段
        for (int i = 0; i < newColumnArr.length; i++) {
            if (i == newColumnArr.length - 1) {
                // 最后一个
                copySQLStr.append("' ' from " + tempTableName);
            } else {
                // 不是最后一个
                copySQLStr.append("' ',");
            }
        }
       
        db.execSQL(copySQLStr.toString());
 
        // 删除旧表
        db.execSQL("drop table " + tempTableName);
 
        // 关闭游标
        cursor.close();
    }

还是解释一下这个方法的参数吧,里面的逻辑就不再过多解释了:

            第一个参数 SQLiteDatabase db ,很简单,数据库对象,需要对其操作的数据库!

            第二个参数 String[] newColumnArr ,需要添加新列的列名数组!

            第三个参数 String oldTableName ,需要升级的表名!

@希望能帮到大家!

相关文章

  • Android数据库表升级(添加列),并保留原表中的数据

    步骤: 1、首先第一步是更改数据库的 version,当检测到你当前版本比之前的高后会执行onUpgrade(SQ...

  • Android 数据库更新

    Android 版本升级中,有时在添加新功能时 会涉及 数据库 表 或 字段(列)的添加,所以我们翻开来讨论。 一...

  • DDL-数据定义语言

    1、库 创建数据库 删除数据库 2、表 创建表 删除表 3、列 增加列 删除列 修改列 4、键 添加主键 删除主键...

  • 数据库笔记-SQL表连接

    表操作 创建表 修改表 添加列 删除列 删除表 表连接 关系型数据库,一个表就是数据之间的关系,而表与表的关系连接...

  • 技术 | SQL语句大全

    语 句 功 能 数据操作 SELECT——从数据库表中检索数据行和列INSERT——向数据库表添加新数据行DELE...

  • 官方修正典藏版SQL 语句大全(一)

    --语 句 功 能 --数据操作 SELECT--从数据库表中检索数据行和列INSERT--向数据库表添加新数据行...

  • 不删除原有数据的情况下更新数据库表

    动态添加列,可以避免更新数据库时删除表中数据; 在函数onUpgrade中调用:

  • DDL(数据库、表的基本操作)

    数据库的创建、删除、查看表的基本操作,创建表,删除表,查看表,修改表(修改表名称,添加列,修改列的名称) prim...

  • Room 修改表主键

    该篇使用较传统方式来修改表的主键,步骤在表结构中将原主键删除添加新主键升级数据库表 升级数据库表步骤创建一个新临时...

  • Android jetpack (Room篇2)

    基于上一篇的demo,记录一下升级数据库的笔记。 在表中添加一列性别 在database中添加语句 生成db时设置...

网友评论

      本文标题:Android数据库表升级(添加列),并保留原表中的数据

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