一个迁移文件中的多个迁移语句
Posted
技术标签:
【中文标题】一个迁移文件中的多个迁移语句【英文标题】:Multiple migration statements in one migration file 【发布时间】:2016-02-03 19:31:17 【问题描述】:我正在尝试在单个迁移文件中执行多个迁移语句,以便一次更改同一张表的多个列。
我想知道我是否以书面方式进行操作,或者是否有更好和更合适的方式:
迁移代码
module.exports =
up: function(queryInterface, Sequelize, done)
queryInterface.changeColumn('users', 'name',
type: Sequelize.STRING,
allowNull: false,
require: true,
unique: true
).success(function()
queryInterface.changeColumn('users', 'address',
type: Sequelize.STRING,
allowNull: false,
require: true,
unique: true
).success(function()
queryInterface.changeColumn('users', 'city',
type: Sequelize.STRING,
allowNull: false,
require: true,
unique: true
).success(function()
queryInterface.changeColumn('users', 'state',
type: Sequelize.STRING,
allowNull: false,
require: true,
defaultValue: "ncjnbcb"
);
done();
);
);
);
;
但我遇到一个错误,上面写着:
TypeError: undefined is not a function
由于我在迁移中找不到任何调试错误的方法,如果有人帮助我解决它,或者如果可能的话,请告诉我们如何找出迁移中的错误。
【问题讨论】:
【参考方案1】:您的 TypeError 可能是因为您没有返回任何内容。 docs 说每个迁移函数都应该返回一个 Promise。没有提到done
回调。
为此,请尝试以下操作:
return Promise.all([
queryInterface.changeColumn...,
queryInterface.changeColumn...
]);
【讨论】:
请提供有用的反馈? 这个方法不太对。任何失败的查询都会导致迁移卡住。见github.com/sequelize/cli/issues/133#issuecomment-236402184 正如@KevinCarmody 所提到的,在一个文件中执行多个事务会使您面临进入不可恢复状态的风险。此外,使用Promise.all
将并行运行迁移。这些天你最好使用async
和await
。
此时我的回答已经过时了。从某种意义上说,它解决了 OP 的主要问题是正确的,但请参阅其他答案以了解如何编写更好的实现。【参考方案2】:
module.exports =
up: async (queryInterface, Sequelize) =>
try
await queryInterface.addColumn('User', 'name',
type: Sequelize.STRING
);
await queryInterface.addColumn('User', 'nickname',
type: Sequelize.STRING
);
return Promise.resolve();
catch (e)
return Promise.reject(e);
,
down: async (queryInterface, Sequelize) =>
try
await queryInterface.removeColumn('Challenges', 'name');
await queryInterface.removeColumn('Challenges', 'nickname');
return Promise.resolve();
catch (e)
return Promise.reject(e);
;
【讨论】:
【参考方案3】:在事务中使用Promise.all
(更安全的迁移):
module.exports =
up: async (queryInterface, Sequelize) =>
return queryInterface.sequelize.transaction(t =>
return Promise.all([
queryInterface.changeColumn('users', 'name',
type: Sequelize.STRING ,
transaction: t
),
queryInterface.changeColumn('users', 'address',
type: Sequelize.STRING ,
transaction: t
),
queryInterface.changeColumn('users', 'city',
type: Sequelize.STRING ,
transaction: t
)
]);
);
,
down: async (queryInterface, Sequelize) =>
return queryInterface.sequelize.transaction((t) =>
return Promise.all([
queryInterface.removeColumn('users', 'name', transaction: t ),
queryInterface.removeColumn('users', 'address', transaction: t ),
queryInterface.removeColumn('users', 'city', transaction: t )
])
)
;
如果某些查询被拒绝,则在没有事务的情况下使用 Promise.all
会导致问题。使用事务是安全的,这样所有操作都会成功执行,否则不会进行任何更改。
【讨论】:
关于最后一句话,这应该是正确的答案 我尝试使用 return promise.all,但工作只是挂在那里。【参考方案4】:所以这是 2 个答案的组合。
@Firmino Changani - 效果很好,但即使有些迁移失败也会完成一些迁移
@Aswin Sanakan - 表示它们都可以迁移,或者没有迁移,但如果第二次迁移依赖于第一次迁移,它将不起作用
我正在创建一个表并向该表添加一个特殊索引。所以我最终将它们结合起来,以下对我有用:
'use strict';
module.exports =
up: async (queryInterface, Sequelize) =>
return queryInterface.sequelize.transaction(async t =>
try
await queryInterface.createTable(
'phonenumbers',
id:
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
,
full_number:
type: Sequelize.STRING,
unique: true
,
phone:
type: Sequelize.STRING
,
extension:
type: Sequelize.INTEGER,
,
country_id:
type: Sequelize.INTEGER
,
is_valid_format:
type: Sequelize.BOOLEAN
,
type:
type: Sequelize.STRING
,
createdAt:
allowNull: false,
type: Sequelize.DATE
,
updatedAt:
allowNull: false,
type: Sequelize.DATE
,
,
transaction: t
),
await queryInterface.addIndex(
'phonenumbers',
['phone'],
name: 'constraint-phone-extension',
where: extension: null,
transaction: t
)
return Promise.resolve();
catch (e)
return Promise.reject(e);
);
,
down: async (queryInterface, Sequelize) =>
return queryInterface.sequelize.transaction(async t =>
try
await queryInterface.dropTable('phonenumbers', transaction: t ),
return Promise.resolve();
catch (e)
return Promise.reject(e);
)
;
【讨论】:
以上是关于一个迁移文件中的多个迁移语句的主要内容,如果未能解决你的问题,请参考以下文章
运行nestjs应用程序时typeorm迁移中的“不能在模块外使用import语句”