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

Aut*_*ico 5 postgresql sequelize.js

有没有办法强制 Sequelize.js 添加IF NOT EXISTS到由queryInterface.addColumnqueryInterface.addIndex方法创建的 Postgres SQL ?

根据 Postgres Docs,Alter Table Add ColumnCreate Index 都支持

我在没有任何运气的情况下浏览了 Sequelize.js 文档,并且我试图通过代码找出 SQL 是如何生成的,但我还没有任何运气。


一点背景,或“为什么”

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

所有这些都适用于每个人,queryInterface.createTable因为IF NOT EXISTS是自动添加的。

小智 13

我有一个类似的问题,除了在我的情况下,我只对 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
    );
  });
Run Code Online (Sandbox Code Playgroud)


pio*_*ias 8

addColumn函数来自queryGenerator被调用的方法addColumnQuery,该方法接受三个参数 - tablekeydataType。使用它们会创建一个查询,看起来像这样

let query = `ALTER TABLE ${quotedTable} ADD COLUMN ${quotedKey} ${definition};`;
Run Code Online (Sandbox Code Playgroud)

因此,如您所见,没有将IF NOT EXISTS子句添加到查询字符串的选项。addIndex不幸的是,同样涉及该方法。但是,您可以使用普通查询来执行一些非典型操作

queryInterface.sequelize.query(...);
Run Code Online (Sandbox Code Playgroud)

  • 是的,我发现我自己查看了代码库。我正在考虑在 repo 上创建一个 PR 来启用这个功能,但是我最终做的是手动更新 `SequelizeMeta` 来伪造迁移的运行。 (2认同)

小智 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);
            }
        });
Run Code Online (Sandbox Code Playgroud)


Dim*_*tri 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) => {
    ...
  },
};

Run Code Online (Sandbox Code Playgroud)