Sequelize迁移向addIndex和addColumn添加“IF NOT EXISTS”

9
有没有一种方法可以强制Sequelize.js在queryInterface.addColumnqueryInterface.addIndex方法创建的Postgres SQL中添加IF NOT EXISTS?根据Postgres文档,Alter Table Add ColumnCreate Index都支持这个选项。我已经查看了Sequelize.js文档,但没有找到相关内容。我也试图查看代码以了解SQL是如何生成的,但是还没有成功。

背景简介,或“为什么创建此策略”

我试图为一个现有的postgres实例创建迁移策略,并且目前已经创建了一个Sequelize迁移集,该集将从“空”迁移到当前模式。现在,我想要简单地在我的生产服务器上运行它,其中所有数据都已经存在,以便下一次我创建迁移时可以运行它。

对于每个queryInterface.createTable,所有这些都很好工作,因为IF NOT EXISTS会自动添加。

4个回答

19

我有类似的问题,不过我的情况只需要在addColumn IF NOT EXIST上感兴趣。

您可以通过两个步骤的解决方案来实现,使用queryInterface.describeTable。给定表名称,该函数将返回包含所有现有列的表定义。如果需要添加的列不存在,则调用queryInterface.addColumn函数。

const tableName = 'your_table_name';

queryInterface.describeTable(tableName)
  .then(tableDefinition => {
    if (tableDefinition.yourColumnName) {
      return Promise.resolve();
    }

    return queryInterface.addColumn(
      tableName,
      'your_column_name',
      { type: Sequelize.STRING } // or a different column
    );
  });

8

addColumn函数来自于调用了addColumnQueryqueryGenerator方法。该方法接收三个参数-tablekeydataType,并利用它们创建一个类似于以下的查询:

let query = `ALTER TABLE ${quotedTable} ADD COLUMN ${quotedKey} ${definition};`;

因此,您可以看到,在查询字符串中没有添加 IF NOT EXISTS 子句的选项。同样,addIndex 方法也存在相同的问题。不过,您可以使用普通查询来执行一些非典型操作。

queryInterface.sequelize.query(...);

2
是的,我自己在浏览存储库时找到了那段代码。我正在考虑在存储库上创建一个PR以启用此功能,但我最终所做的是手动更新“SequelizeMeta”以模拟迁移的运行。 - Automatico
@Cort3z,你最终有为此做出PR吗? - NotSimon
@Simon 我从来没有这样做过。对我来说,这只是一个一劳永逸的工作。我不太记得了,但我可能使用了PSequel或其他数据库管理工具手动更新了我的数据库。 - Automatico
@Cort3z 嗯,我最终选择了使用原始查询来检查现有的索引。感谢您的跟进! - NotSimon

6

语句 if (!tableDefinition.yourColumnName) 无法检查列是否存在。 正确的方式是:

return queryInterface.describeTable(tableName).then(tableDefinition => {
            if (!tableDefinition[columnName]){
                return queryInterface.addColumn(tableName, columnName, {
                    type: Sequelize.JSON
                });
            } else {
                return Promise.resolve(true);
            }
        });

谢谢!正是我所需要的。 - Natashz

6
一个小的工作示例:
module.exports = {
  /**
   * @description Up.
   * @param {QueryInterface} queryInterface
   * @return Promise<void>
   */
  up: async (queryInterface) => {
    const tableDefinition =  await queryInterface.describeTable('group');
    const promises = [];

    return queryInterface.sequelize.transaction((transaction) => {
      if (!tableDefinition.column1) {
        promises.push(queryInterface.addColumn(
          'group',
          'column1',
          {
            type: queryInterface.sequelize.Sequelize.STRING,
            allowNull: true,
          },
          {transaction},
        ));
      }

      if (!tableDefinition.oauth2_token_expire_at) {
        promises.push(queryInterface.addColumn(
          'group',
          'column2',
          {
            type: queryInterface.sequelize.Sequelize.DATE,
            allowNull: true,
          },
          {transaction},
        ));
      }

      return Promise.all(promises);
    });
  },
  /**
   * @description Down.
   * @param {QueryInterface} queryInterface
   * @return Promise<void>
   */
  down: (queryInterface) => {
    ...
  },
};


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接