【问题标题】: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

由于我在迁移中找不到任何调试错误的方法,如果有人帮助我解决它,或者如果可能的话,请告诉我们如何找出迁移中的错误。

【问题讨论】:

    标签: node.js error-handling migration sails.js sequelize.js


    【解决方案1】:

    您的 TypeError 可能是因为您没有返回任何内容。 docs 说每个迁移函数都应该返回一个 Promise。没有提到done 回调。

    为此,请尝试以下操作:

    return Promise.all([
      queryInterface.changeColumn..., 
      queryInterface.changeColumn...
    ]);
    

    【讨论】:

    • 请提供有用的反馈?
    • 这个方法不太对。任何失败的查询都会导致迁移卡住。见github.com/sequelize/cli/issues/133#issuecomment-236402184
    • 正如@KevinCarmody 所提到的,在一个文件中执行多个事务会使您面临进入不可恢复状态的风险。此外,使用Promise.all 将并行运行迁移。这些天你最好使用asyncawait
    • 此时我的回答已经过时了。从某种意义上说,它解决了 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);
            }
          })
        }
      };
      

      【讨论】:

        猜你喜欢
        • 2012-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-17
        • 1970-01-01
        • 1970-01-01
        • 2019-10-02
        • 1970-01-01
        相关资源
        最近更新 更多