【问题标题】:SQLite DB migration to copy, parse and paste data to another columnSQLite DB 迁移将数据复制、解析和粘贴到另一列
【发布时间】:2021-12-08 20:24:10
【问题描述】:

我有一个名为start_time 的列,它在my_table 中属于字符串类型。我想创建一个名为 start_time_int 的附加列(附加,因为项目的某些部分需要 String 类型,而有些部分使用 int 类型会做得更好)我从 start_time 复制所有值,将它们解析为 long并将它们粘贴到start_time_int。仅使用 SQL 命令是否可以进行这种迁移?

【问题讨论】:

  • 添加样本数据和期望的结果会很有帮助。 (不是图片)

标签: sql sqlite android-sqlite


【解决方案1】:

仅使用 SQL 命令可以进行这种迁移吗?

是的,至少可以达到最终的结果。

但是,start_time 的格式很重要

此外,可能不需要迁移,因为 start_time 的格式很可能动态转换结果并且不会两次存储相同的信息。

假设 start_time 的格式为 YYYY-MM-DD hh:mm 例如2021-10-01 10:25 那么由于格式是 SQLite 可识别的格式,您可以在查询表时使用 strftime('%s',start_time) AS start_time_int 获取长版本,并且将有一个 start_time_int 列,它是一个整数(长)。

这是一个演示应用程序,它显示了基于上述格式的 start_time 的两种技术。

数据库有两个表 table1table2,它们最初具有相同的架构 _id 列和 start_time 栏目。

当数据库版本从 1 增加到 2 时,通过 ALTER TABLE table1 ADD COLUMN start_time_int INTEGERonUpgrade 方法中添加一个额外的列 start_time_int,这之后是一个 UPDATE table1 SET start_time_int = strftime('%s',start_time) WHERE start_time_int IS NULL; 设置 start_time_int 值(因为在 start_time_int 列定义中没有指定 DEFAULT,所以设置为 null)。

  • 请注意,为了适应新安装,onCreate 版本也已更改。由于此演示旨在测试版本之间的切换,onCreate 方法具有应用相应表创建的逻辑。

但是,table2 保持不变。此表用于说明无需更改表,因为 Long 值很容易提取。

数据库助手(扩展 SQLiteOpenHelper 的类)DBHelper :-

class DBHelper extends SQLiteOpenHelper {

    public  static final String DBNAME = "thedatabase.db";
    public static final int DBVERSION = 1; /*<<<<<<<< */
    public static final String TABLE1_NAME = "table1";
    public static final String TABLE2_NAME = "table2";
    public static final String ID_COLUMN = BaseColumns._ID;
    public static final String START_TIME_COLUMN = "start_time";
    public static final String START_TIME_INT_COLUMN = "start_time_int";

    SQLiteDatabase db;

    private static volatile DBHelper instance;

    private DBHelper(Context context) {
        super(context,DBNAME,null,DBVERSION);
        db = this.getWritableDatabase();
    }

    public static DBHelper getInstance(Context context) {
        if (instance == null) {
            instance = new DBHelper(context);
        }
        return instance;
    }


    @Override
    public void onCreate(SQLiteDatabase db) {
        if (DBVERSION == 1) {
            db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE1_NAME + " (" +
                    ID_COLUMN + " INTEGER PRIMARY KEY" +
                    ", " + START_TIME_COLUMN + " TEXT" +
                    ")");
        } else {
            db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE1_NAME + " (" +
                    ID_COLUMN + " INTEGER PRIMARY KEY" +
                    ", " + START_TIME_COLUMN + " TEXT " +
                    ", " + START_TIME_INT_COLUMN + " INTEGER " +
                    ")");
        }
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE2_NAME + " (" +
                ID_COLUMN + " INTEGER PRIMARY KEY" +
                ", " + START_TIME_COLUMN + " TEXT" +
                ")");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        if (oldVersion < 2) {
            Log.d("ONUPGRADE", "On Upgrade called. Oldversion is " + oldVersion + " New version is " + newVersion);
            db.execSQL("ALTER TABLE " + TABLE1_NAME + " ADD COLUMN " + START_TIME_INT_COLUMN + " INTEGER;");
            db.execSQL("UPDATE " + TABLE1_NAME + " SET " + START_TIME_INT_COLUMN + " = strftime('%s'," + START_TIME_COLUMN + ") WHERE " + START_TIME_INT_COLUMN + " IS NULL;");
        }
    }

    public long insert(String tableName, String start_time) {
        ContentValues cv = new ContentValues();
        cv.put(START_TIME_COLUMN,start_time);
        return db.insert(tableName,null,cv);
    }

    @SuppressLint("Range")
    public void logTable2() {
        Cursor csr = db.query(TABLE2_NAME,
                new String[]{
                        ID_COLUMN,
                        START_TIME_COLUMN,
                        "strftime('%s'," + START_TIME_COLUMN + ") AS " + START_TIME_INT_COLUMN
                },
                null,null,null,null,null
        );
        while(csr.moveToNext()) {
            Log.d(
                    "TABLE2INFO",
                    "StartTime = " + csr.getString(csr.getColumnIndex(START_TIME_COLUMN)) +
                            " AS INTEGER(long) " + csr.getLong(csr.getColumnIndex(START_TIME_INT_COLUMN))
            );
        }
    }

    @SuppressLint("Range")
    public void logTable1V1() {
        Cursor csr = db.query(TABLE2_NAME,
                null, /* (all columns) */
                null,null,null,null,null
        );
        while(csr.moveToNext()) {
            Log.d(
                    "TABLE1V1INFO",
                    "StartTime = " + csr.getString(csr.getColumnIndex(START_TIME_COLUMN))
            );
        }
    }

    @SuppressLint("Range")
    public void logTable1V2() {
        Cursor csr = db.query(TABLE1_NAME,
                null, /* (all columns) */
                null,null,null,null,null
        );
        DatabaseUtils.dumpCursor(csr);
        while(csr.moveToNext()) {
            Log.d(
                    "TABLE1V2INFO",
                    "StartTime = " + csr.getString(csr.getColumnIndex(START_TIME_COLUMN)) +
                            " AS INTEGER(Long)" + csr.getLong(csr.getColumnIndex(START_TIME_INT_COLUMN))
            );
        }
    }
}
  • 注意 3 logTable??一种用于table1的V1,一种用于table1的V2,一种用于table2的方法。

这是 Activity 中的代码,即打开数据库的 MainActivity,在版本为 1 时将一些行插入 table1 和 table2,每个表的行相同。如果版本为 1,则使用 logTableV1 方法将数据写入日志。如果版本为 2,则使用 logTableV2 将表写入具有新 start_time_int 值的日志。

在这两种情况下,logTable2 方法都会写入 start_time 和 start_time_int,后者已在 SQL 中动态生成。

结果

运行 1 - 使用版本 1 进行新安装:-

2021-10-23 08:10:33.974 D/TABLE1V1INFO: StartTime = 2021-10-01 10:25
2021-10-23 08:10:33.974 D/TABLE1V1INFO: StartTime = 2021-10-02 11:15
2021-10-23 08:10:33.975 D/TABLE2INFO: StartTime = 2021-10-01 10:25 AS INTEGER(long) 1633083900
2021-10-23 08:10:33.975 D/TABLE2INFO: StartTime = 2021-10-02 11:15 AS INTEGER(long) 1633173300 

运行 2 - 版本更改为 2:-

2021-10-23 08:15:23.944 D/TABLE1V2INFO: StartTime = 2021-10-01 10:25 AS INTEGER(Long)1633083900
2021-10-23 08:15:23.944 D/TABLE1V2INFO: StartTime = 2021-10-02 11:15 AS INTEGER(Long)1633173300
2021-10-23 08:15:23.945 D/TABLE2INFO: StartTime = 2021-10-01 10:25 AS INTEGER(long) 1633083900
2021-10-23 08:15:23.945 D/TABLE2INFO: StartTime = 2021-10-02 11:15 AS INTEGER(long) 1633173300

如前所述,start_time 的格式很重要,如果不是 YYYY-MM-DD hh:mm,则可能需要对上述内容进行更改。但是,动态提取重新格式化的数据或更改表然后更新的原则适用。

您不妨考虑阅读SQLite - Date and Time Functions

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-31
    • 2014-03-25
    • 1970-01-01
    相关资源
    最近更新 更多