我有一个使用枚举类型的表列。我希望更新枚举类型有一个额外的可能值。我不想删除任何现有的值,只是添加新的值。最简单的方法是什么?


当前回答

来自Postgres 9.1文档:

ALTER TYPE name ADD VALUE new_enum_value [ { BEFORE | AFTER } existing_enum_value ]

例子:

ALTER TYPE user_status ADD VALUE 'PROVISIONAL' AFTER 'NORMAL'

其他回答

如果你遇到这样的情况,你应该在事务中添加枚举值,例如在ALTER TYPE语句的flyway migration中执行它,你将得到错误error: ALTER TYPE…ADD不能在事务块中运行(参见flyway issue #350),你可以直接将这样的值添加到pg_enum中作为工作区(type_egais_units是目标enum的名称):

INSERT INTO pg_enum (enumtypid, enumlabel, enumsortorder)
    SELECT 'type_egais_units'::regtype::oid, 'NEW_ENUM_VALUE', ( SELECT MAX(enumsortorder) + 1 FROM pg_enum WHERE enumtypid = 'type_egais_units'::regtype )

不能添加注释到适当的位置,但ALTER TABLE foo ALTER COLUMN bar TYPE new_enum_type USING bar::text::new_enum_type默认列失败。我不得不:

ALTER COLUMN bar DROP DEFAULT

然后就成功了。

如果你正在使用Postgres 12(或更高版本),你可以运行ALTER TYPE…在交易(文档)中增加价值。

如果ALTER TYPE…ADD VALUE(向枚举中添加新值的表单 类型)在事务块内执行,则新值不能为 一直使用到事务提交之后。

因此在迁移中不需要任何hack。

UPD:这里有一个例子(感谢Nick)

添加一个新值

补充@Dariusz 1

对于Rails 4.2.1,有这样的文档部分:

==事务性迁移

如果数据库适配器支持DDL事务,则所有迁移都将支持 自动包装在事务中。有一些查询 但是不能在事务中执行,对于这些情况 您可以关闭自动事务处理。

class ChangeEnum < ActiveRecord::Migration
  disable_ddl_transaction!

  def up
    execute "ALTER TYPE model_size ADD VALUE 'new_value'"
  end
end

一个可能的解决方案如下;前提条件是,使用的枚举值中没有冲突。(例如,当删除一个枚举值时,确保该值不再使用。)

-- rename the old enum
alter type my_enum rename to my_enum__;
-- create the new enum
create type my_enum as enum ('value1', 'value2', 'value3');

-- alter all you enum columns
alter table my_table
  alter column my_column type my_enum using my_column::text::my_enum;

-- drop the old enum
drop type my_enum__;

同样,用这种方法列的顺序也不会改变。