为什么Knex中我的dropTimestamps迁移操作没有生效?
问题根源
你遇到的问题是异步执行顺序和Knex Schema构建器的执行机制不匹配导致的,核心有两个错误:
- Knex的
schema.table回调执行时会同步收集所有表结构变更操作,回调执行完成后就会拼接SQL提交执行。你在回调内部调用的hasColumn是异步方法,等你拿到exists结果执行table.dropTimestamps()时,表结构变更队列已经提交完成,这个删除操作根本不会被收集到执行队列中。 - 你没有将
hasColumn返回的Promise返回给up函数,Knex迁移执行器不会等待这个异步逻辑执行完成,就会认为该迁移已经执行结束,自然看不到对应的DROP COLUMN语句。
修复方案
把字段存在性判断提到schema.table调用的外层,先拿到判断结果再决定是否执行删除操作,正确写法如下:
Promise链式写法
exports.up = function(knex) { return knex.schema.hasColumn('ab_camp_user', 'created_at') .then(function(exists) { console.log("ab_camp_user.created_at exists = ", exists); if (exists) { return knex.schema.table('ab_camp_user', function(table) { table.dropTimestamps(); }); } }); };
async/await 写法(更易读)
exports.up = async function(knex) { const exists = await knex.schema.hasColumn('ab_camp_user', 'created_at'); console.log("ab_camp_user.created_at exists = ", exists); if (exists) { await knex.schema.table('ab_camp_user', table => { table.dropTimestamps(); }); } };
修改后Knex会先完成字段存在性查询,再执行对应的表结构删除操作,生成的DROP COLUMN语句就能正常执行了。
内容的提问来源于stack exchange,提问作者bjlevine
相关产品推荐
相关产品推荐

