我有一个使用枚举类型的表列。我希望更新枚举类型有一个额外的可能值。我不想删除任何现有的值,只是添加新的值。最简单的方法是什么?
当前回答
如上所述,ALTER命令不能写入事务内部。建议的方法是直接插入到pg_enum表中,从pg_type表中检索typelem并计算下一个enumsortorder号;
以下是我使用的代码。检查插入前是否存在重复值(enumtypid和enumlabel名称之间的约束)
INSERT INTO pg_enum (enumtypid, enumlabel, enumsortorder)
SELECT typelem,
'NEW_ENUM_VALUE',
(SELECT MAX(enumsortorder) + 1
FROM pg_enum e
JOIN pg_type p
ON p.typelem = e.enumtypid
WHERE p.typname = '_mytypename'
)
FROM pg_type p
WHERE p.typname = '_mytypename'
AND NOT EXISTS (
SELECT * FROM
pg_enum e
JOIN pg_type p
ON p.typelem = e.enumtypid
WHERE e.enumlabel = 'NEW_ENUM_VALUE'
AND p.typname = '_mytypename'
)
注意,在pg_type表中,类型名前面有下划线。此外,where子句中的typname必须全部小写。
现在这可以安全地写入您的db migrate脚本。
其他回答
如果你正在使用Postgres 12(或更高版本),你可以运行ALTER TYPE…在交易(文档)中增加价值。
如果ALTER TYPE…ADD VALUE(向枚举中添加新值的表单 类型)在事务块内执行,则新值不能为 一直使用到事务提交之后。
因此在迁移中不需要任何hack。
UPD:这里有一个例子(感谢Nick)
添加一个新值
最简单的方法:去掉枚举。它们不容易修改,因此应该很少使用。
以防万一,如果你在使用Rails,你有几个语句,你需要一个一个地执行,比如:
execute "ALTER TYPE XXX ADD VALUE IF NOT EXISTS 'YYY';"
execute "ALTER TYPE XXX ADD VALUE IF NOT EXISTS 'ZZZ';"
如上所述,ALTER命令不能写入事务内部。建议的方法是直接插入到pg_enum表中,从pg_type表中检索typelem并计算下一个enumsortorder号;
以下是我使用的代码。检查插入前是否存在重复值(enumtypid和enumlabel名称之间的约束)
INSERT INTO pg_enum (enumtypid, enumlabel, enumsortorder)
SELECT typelem,
'NEW_ENUM_VALUE',
(SELECT MAX(enumsortorder) + 1
FROM pg_enum e
JOIN pg_type p
ON p.typelem = e.enumtypid
WHERE p.typname = '_mytypename'
)
FROM pg_type p
WHERE p.typname = '_mytypename'
AND NOT EXISTS (
SELECT * FROM
pg_enum e
JOIN pg_type p
ON p.typelem = e.enumtypid
WHERE e.enumlabel = 'NEW_ENUM_VALUE'
AND p.typname = '_mytypename'
)
注意,在pg_type表中,类型名前面有下划线。此外,where子句中的typname必须全部小写。
现在这可以安全地写入您的db migrate脚本。
如果你遇到这样的情况,你应该在事务中添加枚举值,例如在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 )
推荐文章
- 如何改变一个列的数据类型在PostgreSQL表?
- 获取PostGIS版本
- 如何添加“删除级联”约束?
- 我如何得到“id”后插入到MySQL数据库与Python?
- 什么是ORM,它是如何工作的,我应该如何使用它?
- 我如何使一个enum可解码在Swift?
- 如何将PostgreSQL从9.6版本升级到10.1版本而不丢失数据?
- 如何设置enum为空
- 为现有数据库生成ERD
- BASE术语解释
- 选择Enum类型的默认值而无需更改值
- PostgreSQL错误:由于与恢复冲突而取消语句
- 是否有一种方法来检查是否int是合法的enum在c# ?
- 按IN值列表排序
- 如何在Postgres 9.4中对JSONB类型的列执行更新操作