如何使用数据迁移更新sqlite3架构

时间:2016-06-11 15:08:08

标签: database sqlite database-migration data-migration

我可能有一个特殊的数据迁移问题:

  1. 我有一个已存在且已填充的SQLite3数据库。
  2. 我确实收到了一个(希望兼容的)数据库的新架构。
  3. 结果应该是一个新数据库,根据新模式构建,尽可能包含旧数据库内容。

    鉴于SQLite3 ALTER语句和我们的工作流程都有限制,可以安全地假设:

    • 正常情况下将新列添加到表的末尾。
    • 添加的列(字段)将具有默认值或可以保留为NULL。
    • 很少会添加一些表格。
    • 很少会删除某些表或列。
    • 不会重命名表/列。
    • 不会发生任何列重组。

    注意:如果新架构与旧架构不兼容(即:上述任何假设都不成立),则表示接受失败。

    我尝试过这个脚本(旧数据库为data.sql3,新架构为data.schema):

    mkdir tmp
    cd tmp
    
    #compute old DB schema
    sqlite3 ../data.sql3 .schema >old_s
    
    #purge new schema for any initialization...
    grep -v ^INSERT ../data.schema >data.schema
    #... create a dew, empty DB...
    sqlite3 new.sql3 <data.schema
    #... and compute a standard schema
    #(this is done to avoid typing differences)
    sqlite3 new.sql3 .schema >new_s
    
    #iff the schemas are different
    if ! diff -q old_s new_s
    then
      #save old DB
      mv ../data.sql3 .
      #dump contents
      sqlite3 data.sql3 .dump >old_d
      #expunge all statements needed to recreate DB/Tables
      #new_d contains only INSERT statements
      grep -v -f old_s old_d >new_d
      #add old DB content to new DB
      sqlite3 new.sql3 <new_d
      #move new DB in place
      mv new.sql3 ../data.sql3
    fi
    cd ..
    

    这可以检测更改,但无法重新填充新数据库,因为.dump不包含列名,因此插入失败(缺少值)。

    我正在寻找的方法是强制sqlite3 DB .dump输出包含所有字段名称的INSERT语句(通常它依赖于位置),或者它是不可能的,某种方式告诉sqlite3 DB <new_d将任何未定义的字段视为null或默认值(不失败)。

    同样欢迎任何其他方式来达到相同的结果(不需要知道什么,确切地说,已被修改)。

1 个答案:

答案 0 :(得分:0)

为了能够将包含较少列的转储插入/导入到表中,您可以为新的附加列提供默认值,或者只是将它们设置为NULLCREATE TABLEALTER TABLE的约束子句相同:

http://www.sqlite.org/syntax/column-constraint.html

-- newColumn is set to a default value if not provided with INSERT
alter table myTable
add column newColumn INTEGER NOT NULL default 0;

-- newColumn may be NULL, which is the default if not provided with INSERT
alter table myTable
add column newColumn INTEGER;

-- It is also valid to combine NULL and DEFAULT constraints
alter table myTable
add column newColumn INTEGER default 0;

请注意,为了使INSERT语句与新列一起使用,必须提供列名。