Alter table modify enum in Knex js for Postgresql 给出错误

Alter table modify enum in Knex js for Postgresql gives error

我正在使用 knex js 和 postgresql 数据库。我使用迁移文件创建了 table knex migrate:make create_car_table。在此我添加了一列 fuel_type。 table.enu('fuel_type', ['PETROL', 'DIESEL', 'CNG']).

现在我需要更改 table 并且我需要这些枚举值 ['HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL']

我使用 knex migrate:make alter_car_table 创建了另一个迁移文件并添加了以下代码

exports.up = function(knex, Promise) {
    return knex.schema.alterTable('car', function (table) {
        table.enu('fuel_type', ['HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL']).alter();
    });
};

exports.down = function(knex, Promise) {
    return knex.schema.alterTable('car', function (table) {
        table.enu('fuel_type', ['PETROL', 'DIESEL', 'CNG']).alter();
    });
};

当我 运行 knex migrate:latest 我得到以下错误。

Knex:warning - migrations failed with error: alter table "car" alter column "fuel_type" type text check ("fuel_type" in ('HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL')) using ("fuel_type"::text check ("fuel_type" in ('HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL'))) - syntax error at or near "check"

为此,我已参考 Knex Js

更改列不适用于 knex 0.13.0 中的枚举类型。

枚举也是作为检查约束实现的,因此要更改它,您需要重新创建。

像这样:

exports.up = function(knex, Promise) {
  return knex.schema.raw(`
    ALTER TABLE "car"
    DROP CONSTRAINT "car_fuel_type_check",
    ADD CONSTRAINT "car_fuel_type_check" 
    CHECK (fuel_type IN ('HYBRID', 'ELECTRIC', 'PETROL', 'DIESEL'))
  `);
};

exports.down = function(knex, Promise) { ... };

您可能需要检查最初由 knex 从数据库生成的约束名称。

目前 knex.schema.raw 是修改枚举的唯一方法。

您首先需要删除现有约束,然后使用新值创建一个新约束。 下面的代码示例应该有所帮助。

exports.up = function(knex, Promise) {
  return knex.schema.raw(`
    ALTER TABLE "car" DROP CONSTRAINT "car_fuel_type_check";
    ALTER TABLE "car" ADD CONSTRAINT "car_fuel_type_check" CHECK (fuel_type IN ('HYBRID'::text, 'ELECTRIC'::text, 'PETROL'::text, 'DIESEL'::text))
  `);
};

// The reverse migration is similar
exports.down = function(knex, Promise) {
  return knex.schema.raw(`
    ALTER TABLE "car" DROP CONSTRAINT "car_fuel_type_check";
    ALTER TABLE "car" ADD CONSTRAINT "car_fuel_type_check" CHECK (fuel_type IN ('PETROL'::text, 'DIESEL'::text, 'CNG'::text));
  `);
};

我假设您的约束名称是 car_fuel_type_check。如果不是,您应该将 car_fuel_type_check 替换为您的约束名称。

由于 alter() 方法不适用于 enu/enum 列,我建议删除该列,然后按照您喜欢的方式重新创建它。例如,如果你想改变枚举文本,你可以这样做:

export async function up(knex: Knex): Promise<void> {
  await knex.schema.alterTable('<table name>', (table) => {
    table.dropColumn('column name');
  });
  await knex.schema.alterTable('<table name>', (table) => {
    table.enu('column name', ['old enum 1', 'old enum 2'])
  });
}

export async function down(knex: Knex): Promise<void> {
  await knex.schema.alterTable('<table name>', (table) => {
    table.dropColumn('column name');
  });

  await knex.schema.alterTable('<table name>', (table) => {
    table.enu('column name', ['new enum 1', 'new enum2'])
  });
}

我们可以使用 knex migrate 更新枚举的值。

exports.up = async function(knex) {
    return knex.raw(`
    ALTER TABLE organizations 
    CHANGE subscriptionStatus subscriptionStatus enum('Past Due','Paid','Free Trial','Free Trial Expired','Pre Trial','ddd') DEFAULT 'Pre Trial';
    `);
  };
  
  exports.down = async function(knex) {
    return knex.raw(`
    ALTER TABLE organizations 
    CHANGE subscriptionStatus subscriptionStatus enum('Past Due','Paid','Free Trial','Free Trial Expired','Pre Trial') DEFAULT 'Pre Trial';
    `);
  };