我可能有一个特殊的数据迁移问题:
结果应该是一个新数据库,根据新模式构建,尽可能包含旧数据库内容。
鉴于SQLite3 ALTER语句和我们的工作流程都有限制,可以安全地假设:
注意:如果新架构与旧架构不兼容(即:上述任何假设都不成立),则表示接受失败。
我尝试过这个脚本(旧数据库为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
或默认值(不失败)。
同样欢迎任何其他方式来达到相同的结果(不需要知道什么,确切地说,已被修改)。
答案 0 :(得分:0)
为了能够将包含较少列的转储插入/导入到表中,您可以为新的附加列提供默认值,或者只是将它们设置为NULL
。 CREATE TABLE
和ALTER 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
语句与新列一起使用,必须提供列名。