我使用knex.js,它是PostgreSQL的很好的查询生成器。我还没有找到任何文档来说明如何以正确的方式进行迁移回滚。
现在,我只在down
函数中编写反向迁移操作以进行迁移回滚。这是正确的方法吗?
import * as Knex from 'knex';
exports.up = async (knex: Knex): Promise<any> => {
await knex.schema.raw(`
ALTER TABLE IF EXISTS "GOOGLE_CHANNEL"
ADD COLUMN IF NOT EXISTS google_channel_ad_group_cpc_bid INTEGER NOT NULL DEFAULT 0;
`);
await knex.schema.raw(`
UPDATE "GOOGLE_CHANNEL" as gc
SET
google_channel_ad_group_cpc_bid = 7
FROM "CAMPAIGN_TEMPLATE" as ct
WHERE ct.campaign_channel_id = gc.campaign_channel_id;
`);
};
exports.down = async (knex: Knex): Promise<any> => {
// TODO: migration rollback
await knex.schema.raw(``);
};
我有两个问题:
如果up
函数中有很多SQL语句,为了回滚迁移,我也必须在down
函数中写很多SQL语句。
为什么knex.js在不为我们编写反向操作的情况下不进行迁移回滚?我的意思是,knex.js可以拍摄快照或记录数据库的保存点。
答案 0 :(得分:1)
是的,要回滚,请使用迁移脚本的down
函数。运行knex migrate:rollback
时,down
函数将运行。 Knex在数据库中具有元表,这些元表用于确定哪些迁移已在运行或未运行。
例如:
exports.up = function (knex, Promise) {
return knex.schema
.createTable('role', function (table) {
table.increments('role_id').primary();
table.string('title').notNullable().unique();
table.string('description');
table.integer('level').notNullable(),
})
.createTable('user_account', function (table) {
table.increments('user_id').primary();
table.integer('role_id').references('role_id').inTable('role').notNullable();
table.string('username').notNullable().unique();
table.string('passwordHashed').notNullable();
table.string('email', 50).notNullable().unique();
});
};
exports.down = function (knex, Promise) {
return knex.schema
.dropTable('user_account')
.dropTable('role');
};
在这里,我在up函数中创建两个表。 user_account
具有外键约束,并与role
表链接,这意味着我必须在down函数中将user_account
表放在role
表之前。< / p>
在您的情况下,您使用更新语句。在向下功能中,您必须使用硬编码值(迁移之前的旧值)进行新的更新,或者确保将旧值存储在历史记录表中。
关于您的担忧:
是的,如果您添加了很多东西,那么您还必须添加很多代码以撤消所做的任何事情。但是,您可以跳过制作down脚本的步骤,但是您将无法回滚。有些(很多?)选择只前进而不回退。如果他们必须修复某些问题,则无需回滚,而是使用该修复程序制作新的迁移脚本。
我建议您一开始创建down函数。您可以考虑在适当的时候跳过制作它们。那些没有降低功能的人通常必须在部署到生产之前在测试或过渡环境中更彻底地测试其迁移。这是为了确保其有效,因为它们毕竟无法回滚。
我在这里不能真正为Knex创作者回答。但是,您所描述的潜在解决方案基本上是在迁移完成之前备份数据库。毕竟,迁移所做的不仅仅是改变表的布局等。迁移脚本通常还会添加或删除新行。您可以使用备份方法,但必须自己进行备份。
Knex是一个相当简单的查询生成器。如果您希望为您编写迁移脚本,则可能需要完整的OR映射器。