我目前正在尝试使用 PersistenceJS 的迁移插件对现有数据库进行更改。我可以很好地在数据库中添加/编辑/删除项目——但是……
- 如何向现有(!)表中添加一列?
如何更改现有 (!) 列的类型,例如从“文本”到“整数”?
这些更改应保留当前存在的数据。
遗憾的是,文档有点稀缺,也许你能帮忙?
这是当前有效设置:
persistence.store.websql.config(persistence, 'tododatabase', 'todos are fun', 5*1024*1024);
var Todo = persistence.define('Todo', {
task: 'TEXT',
priority: 'INT',
done: 'BOOL'
});
persistence.schemaSync();
function addTodo( item ){
var todo = new Todo();
todo.task = item.task;
todo.priority = item.priority;
todo.done = item.done;
persistence.add(todo);
persistence.flush();
};
function deleteTodo( item, callback ){
// item.id was created automatically by calling "new Todo()"
Todo.all().filter('id','=', item.id ).destroyAll( function(){
persistence.flush( callback );
});
};
有点的迁移代码:
persistence.defineMigration(1, {
up: function() {
this.createTable('Todo', function(t){
t.text('task');
t.integer('priority');
t.boolean('done');
});
},
down: function() {
this.dropTable('Todo');
}
});
persistence.defineMigration(2, {
up: function() {
this.addColumn('Todo', 'due', 'DATE');
},
down: function() {
this.removeColumn('Todo', 'due');
}
});
function migrate( callback ){
console.log('migrating...');
persistence.migrations.init( function(){
console.log('migration init');
// this should migrate up to the latest version, in our case: 2
persistence.migrate( function(){
console.log('migration complete!');
} );
});
}
结果……
- 调用 migrate() 只会记录“迁移初始化”,不会调用完整的处理程序,不会创建“到期”列
- 在调用 migrate() 之前不调用 schemaSync() 正如 Zef Hemel 自己在 this post 中提出的那样产生与 1 相同的结果。
- 将第一行更改为
persistence.store.websql.config(persistence, 'newdatabase', 'testing migration', 5*1024*1024);
,不调用 schemaSync(),只调用migrate() 将成功记录“迁移完成!” — 但它是在一个新的、完全空的数据库“newdatabase”中这样做的,该数据库当然不会保留任何现有数据。
总结
有一个数据库是使用 persistence.store.websql.config(...)
, persistence.define('Todo',...)
创建的和 persistence.schemaSync()
。
我现在想保留该数据库中已经存在的所有数据,但又想
- 将列
priority
的类型从“整数”更改为“文本” - 向所有现有待办事项添加类型为“日期”的
到期
列
如果你能把我推向正确的方向,我将不胜感激!
谢谢!
最佳答案
我终于让它工作了。我想指出一些与我的初始要求有关的问题,以供将来引用。看一下第一个迁移定义:
persistence.defineMigration(1, {
up: function() {
this.createTable('Todo', function(t){
...
毫不奇怪,createTable
将执行此操作:它将执行 SQL 语句 'CREATE TABLE Todo ...'
,如果有已经具有名称 Todo
的表。这就是为什么它适用于新数据库,但不适用于现有数据库。请记住:我已经有一个实时数据库,其中包含需要更新的表“Todo”。如果您是新手(即您没有使用过 schemaSync
),createTable
工作得很好。由于 Migrations 插件不提供 createTableIfNotExists
方法,我需要使用 executeSql
如下:
persistence.defineMigration(1, {
up: function() {
this.executeSql('CREATE TABLE IF NOT EXISTS Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, done BOOL)');
...
现在从架构版本 0 到 1 的迁移成功了,到版本 2 的迁移也成功了。
随着迁移到版本 3,priority
列的类型需要从 int
更改为 text
。这通常使用 ALTER COLUMN
SQL 命令来完成,Web SQL/SQLite 不支持该命令。参见 Omitted Features for SQLite .
使用 SQLite 更改列需要 4 个步骤的解决方法:
persistence.defineMigration(3, {
up: function() {
// rename current table
this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
// create new table with required columns and column types
this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority TEXT, done BOOL)');
// copy contents from old table to new table
this.executeSql('INSERT INTO Todo(id, task, priority, done) SELECT id, task, priority, done FROM OldTodo');
// delete old table
this.executeSql('DROP TABLE OldTodo');
},
...
当然,改变列类型后,'Todo'的实体定义也要改变:
var Todo = persistence.define('Todo', {
task: 'TEXT',
priority: 'TEXT', // was 'INT'
due: 'DATE',
done: 'BOOL'
});
最后,完整的源代码:
persistence.store.websql.config(persistence, 'tododatabase', 'todos are fun', 5*1024*1024);
// persistence.debug = true;
//v0 + v1
// var Todo = persistence.define('Todo', {
// task: 'TEXT',
// priority: 'INT',
// done: 'BOOL'
// });
//v2
// var Todo = persistence.define('Todo', {
// task: 'TEXT',
// priority: 'INT',
// due: 'DATE',
// done: 'BOOL'
// });
//v3
var Todo = persistence.define('Todo', {
task: 'TEXT',
priority: 'TEXT',
due: 'DATE',
done: 'BOOL'
});
persistence.defineMigration(1, {
up: function() {
this.executeSql('CREATE TABLE IF NOT EXISTS Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, done BOOL)');
},
down: function() {
this.dropTable('Todo');
}
});
persistence.defineMigration(2, {
up: function() {
this.addColumn('Todo', 'due', 'DATE');
},
down: function() {
this.removeColumn('Todo', 'due');
}
});
persistence.defineMigration(3, {
up: function() {
// rename current table
this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
// create new table with required columns
this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority TEXT, due DATE, done BOOL)');
// copy contents from old table to new table
this.executeSql('INSERT INTO Todo(id, task, priority, due, done) SELECT id, task, priority, due, done FROM OldTodo');
// delete current table
this.executeSql('DROP TABLE OldTodo');
},
down: function() {
this.executeSql('ALTER TABLE Todo RENAME TO OldTodo');
this.executeSql('CREATE TABLE Todo (id VARCHAR(32) PRIMARY KEY, task TEXT, priority INT, due DATE, done BOOL)');
this.executeSql('INSERT INTO Todo(id, task, priority, due, done) SELECT id, task, priority, due, done FROM OldTodo');
this.executeSql('DROP TABLE OldTodo');
}
});
function migrate( callback ){
console.log('migrating...');
persistence.migrations.init( function(){
console.log('migration init');
persistence.migrate( function(){
console.debug('migration complete!');
callback();
} );
});
};
migrate( onMigrationComplete );
function onMigrationComplete(){
// database is ready. do amazing things...
};
关于javascript - 持久性JS : Updating an existing database using migrate(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24204554/