sql >> データベース >  >> RDS >> PostgreSQL

正しく続編を使用してENUMをドロップして作成しますか?

    更新:これまでに3つのプロジェクトでこれを使用したので、npmモジュールを作成することにしました: https://www.npmjs.com/package/replace-enum-postgresql

    私はこれを行うためのユーティリティを作成しました。これがお役に立てば幸いです。

    utils/replace_enum.js

    'use strict';
    
    /**
     * Since PostgreSQL still does not support remove values from an ENUM,
     * the workaround is to create a new ENUM with the new values and use it
     * to replace the other.
     *
     * @param {String} tableName
     * @param {String} columnName
     * @param {String} defaultValue
     * @param {Array}  newValues
     * @param {Object} queryInterface
     * @param {String} enumName - Optional.
     *
     * @return {Promise}
     */
    module.exports = function replaceEnum({
      tableName,
      columnName,
      defaultValue,
      newValues,
      queryInterface,
      enumName = `enum_${tableName}_${columnName}`
    }) {
      const newEnumName = `${enumName}_new`;
    
      return queryInterface.sequelize.transaction((t) => {
        // Create a copy of the type
        return queryInterface.sequelize.query(`
          CREATE TYPE ${newEnumName}
            AS ENUM ('${newValues.join('\', \'')}')
        `, { transaction: t })
          // Drop default value (ALTER COLUMN cannot cast default values)
          .then(() => queryInterface.sequelize.query(`
            ALTER TABLE ${tableName}
              ALTER COLUMN ${columnName}
                DROP DEFAULT
          `, { transaction: t }))
          // Change column type to the new ENUM TYPE
          .then(() => queryInterface.sequelize.query(`
            ALTER TABLE ${tableName}
              ALTER COLUMN ${columnName}
                TYPE ${newEnumName}
                USING (${columnName}::text::${newEnumName})
          `, { transaction: t }))
          // Drop old ENUM
          .then(() => queryInterface.sequelize.query(`
            DROP TYPE ${enumName}
          `, { transaction: t }))
          // Rename new ENUM name
          .then(() => queryInterface.sequelize.query(`
            ALTER TYPE ${newEnumName}
              RENAME TO ${enumName}
          `, { transaction: t }))
          .then(() => queryInterface.sequelize.query(`
            ALTER TABLE ${tableName}
              ALTER COLUMN ${columnName}
                SET DEFAULT '${defaultValue}'::${enumName}
          `, { transaction: t }));
      });
    }

    これが私のです 移行:

    'use strict';
    
    const replaceEnum = require('./utils/replace_enum');
    
    module.exports = {
      up: (queryInterface, Sequelize) => {
        return replaceEnum({
          tableName: 'invoices',
          columnName: 'state',
          enumName: 'enum_invoices_state',
          defaultValue: 'created',
          newValues: ['archived', 'created', 'paid'],
          queryInterface
        });
      },
    
      down: (queryInterface, Sequelize) => {
        return replaceEnum({
          tableName: 'invoices',
          columnName: 'state',
          enumName: 'enum_invoices_state',
          defaultValue: 'draft',
          newValues: ['archived', 'draft', 'paid', 'sent'],
          queryInterface
        });
      }
    };


    1. Hibernateを使用してPostgreSQL配列をマップする方法

    2. SQLを実行するには何が必要ですか?

    3. MySQLのサブクエリ内から親クエリフィールドを指定するにはどうすればよいですか?

    4. SnowLeopardへのMySQLdbのインストール