【问题标题】:Adding a field to an existing sqlite database将字段添加到现有的 sqlite 数据库
【发布时间】:2011-07-16 00:26:33
【问题描述】:

我已经发布了一个现有的应用程序,我想将位置坐标字段添加到 sqlite 数据库。

我想知道是否可以在不在数据库中创建新表的情况下执行此操作。我不想覆盖用户现有的数据库条目,我只想为现有的数据库条目添加这个新字段并给它一个默认值。

这可能吗?

【问题讨论】:

    标签: android sqlite


    【解决方案1】:

    是的,

    更新表时需要编写onUpgrade() 方法。目前,我使用以下内容创建一个带有新列的新表并复制我所有的当前数据。希望您可以根据自己的代码进行调整。

    @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion);
    
                db.beginTransaction();
                try {
                    db.execSQL("CREATE TABLE IF NOT EXISTS " + DATABASE_UPGRADE);
                    List<String> columns = GetColumns(db, DATABASE_TABLE);
                    db.execSQL("ALTER table " + DATABASE_TABLE + " RENAME TO 'temp_" + DATABASE_TABLE + "'");
                    db.execSQL("create table " + DATABASE_UPGRADE);
                    columns.retainAll(GetColumns(db, DATABASE_TABLE));
                    String cols = join(columns, ","); 
                    db.execSQL(String.format( "INSERT INTO %s (%s) SELECT %s from temp_%s", DATABASE_TABLE, cols, cols, DATABASE_TABLE));
                    db.execSQL("DROP table 'temp_" + DATABASE_TABLE + "'");
                    db.setTransactionSuccessful();
                } finally {
                    db.endTransaction();
                }
            }
        }
    
        public static List<String> GetColumns(SQLiteDatabase db, String tableName) {
            List<String> ar = null;
            Cursor c = null;
            try {
                c = db.rawQuery("select * from " + tableName + " limit 1", null);
                if (c != null) {
                    ar = new ArrayList<String>(Arrays.asList(c.getColumnNames()));
                }
            } catch (Exception e) {
                Log.v(tableName, e.getMessage(), e);
                e.printStackTrace();
            } finally {
                if (c != null)
                    c.close();
            }
            return ar;
        }
    
        public static String join(List<String> list, String delim) {
            StringBuilder buf = new StringBuilder();
            int num = list.size();
            for (int i = 0; i < num; i++) {
                if (i != 0)
                    buf.append(delim);
                buf.append((String) list.get(i));
            }
            return buf.toString();
        }
    

    这包含onUpgrade() 和两个辅助方法。 DATABASE_UPGRADE 是一个包含升级数据库的字符串:

    private static final String DATABASE_UPGRADE =
        "notes (_id integer primary key autoincrement, "
        + "title text not null, "
        + "body text not null, "
        + "date text not null, "
        + "edit text not null, "
        + "reminder text, "
        + "img_source text, "
        + "deletion, "
        + "priority)";
    

    快速说明这是如何工作的:

    1. 检查当前版本的表是否已经存在(它永远不应该存在),因为在这种情况下不应调用 onUpgrade()
    2. 由于失败,从当前表中获取列列表(使用辅助函数GetColumns())。
    3. 将旧表重命名为 temp_OLDTABLENAME。
    4. 创建新版本的数据库附加列(当前为空)。
    5. 从旧版数据库中获取所有信息。
    6. 将其插入新数据库
    7. 删除旧表 (temp_OLDTABLENAME)。

    我尝试编写足够通用的代码,所以我所要做的就是使用附加列更新 DATABASE_UPGRADE,然后它会处理所有其余部分。到目前为止,它已通过 3 次升级为我工作。

    【讨论】:

    • 您能否解释一下这是如何工作的,因为您似乎为DATABASE_UPGRADE 调用了两次create table?也许第二个应该是create table DATABASE_TABLE
    • 但是在你开始工作之前,必须看到this question。一个可能出现的非常基本的问题。
    【解决方案2】:

    您可以使用ALTER TABLE 添加列。

    ALTER TABLE my_table ADD COLUMN location ...;

    【讨论】:

      【解决方案3】:

      使用 SQLiteOpenHelper 的 onUpgrade 方法运行“alter table”语句。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-25
        • 2013-03-10
        相关资源
        最近更新 更多