我有一个使用枚举类型的表列。我希望更新枚举类型有一个额外的可能值。我不想删除任何现有的值,只是添加新的值。最简单的方法是什么?
当前回答
一个可能的解决方案如下;前提条件是,使用的枚举值中没有冲突。(例如,当删除一个枚举值时,确保该值不再使用。)
-- 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__;
同样,用这种方法列的顺序也不会改变。
其他回答
最简单的方法:去掉枚举。它们不容易修改,因此应该很少使用。
更新pg_enum可以工作,就像上面突出显示的中间列技巧一样。你也可以使用USING魔法直接改变列的类型:
CREATE TYPE test AS enum('a', 'b');
CREATE TABLE foo (bar test);
INSERT INTO foo VALUES ('a'), ('b');
ALTER TABLE foo ALTER COLUMN bar TYPE varchar;
DROP TYPE test;
CREATE TYPE test as enum('a', 'b', 'c');
ALTER TABLE foo ALTER COLUMN bar TYPE test
USING CASE
WHEN bar = ANY (enum_range(null::test)::varchar[])
THEN bar::test
WHEN bar = ANY ('{convert, these, values}'::varchar[])
THEN 'c'::test
ELSE NULL
END;
只要没有函数显式地要求或返回该枚举,就没问题。(如果有,pgsql会在删除类型时报错。)
另外,请注意PG9.1引入了一个ALTER TYPE语句,它将对枚举起作用:
http://developer.postgresql.org/pgdocs/postgres/release-9-1-alpha.html
我不知道是否有其他选择,但我们可以使用:
select oid from pg_type where typname = 'fase';'
select * from pg_enum where enumtypid = 24773;'
select * from pg_enum where enumtypid = 24773 and enumsortorder = 6;
delete from pg_enum where enumtypid = 24773 and enumsortorder = 6;
免责声明:我没有尝试过这个解决方案,所以它可能不起作用;-)
您应该查看pg_enum。如果你只想改变一个现有ENUM的标签,一个简单的UPDATE就可以做到。
添加一个新的ENUM值。
首先将新值插入到pg_enum中。如果新值必须是最后一个,那么就完成了。 如果不是(你需要一个新的ENUM值在现有的值之间),你将不得不更新你的表中每个不同的值,从最高到最低… 然后你只需要在pg_enum中以相反的顺序重命名它们。
插图 您有以下一组标签:
ENUM ('enum1', 'enum2', 'enum3')
你想要得到:
ENUM ('enum1', 'enum1b', 'enum2', 'enum3')
然后:
INSERT INTO pg_enum (OID, 'newenum3');
UPDATE TABLE SET enumvalue TO 'newenum3' WHERE enumvalue='enum3';
UPDATE TABLE SET enumvalue TO 'enum3' WHERE enumvalue='enum2';
然后:
UPDATE TABLE pg_enum SET name='enum1b' WHERE name='enum2' AND enumtypid=OID;
等等……
如上所述,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脚本。
推荐文章
- 在MongoDB中查找重复的记录
- 对于PostgreSQL表来说,多大才算太大?
- 如何从枚举中选择一个随机值?
- 模式、表和数据库之间的区别是什么?
- 将一列的多个结果行连接为一列,按另一列分组
- c#中枚举中的方法
- 我看到VARCHAR(255)如此频繁地使用(而不是其他长度),有什么好的原因吗?
- 使用pgadmin连接到heroku数据库
- 在PostgreSQL中快速发现表的行数
- 更改varchar列的大小为较低的长度
- Delete_all vs destroy_all
- 我如何移动一个redis数据库从一个服务器到另一个?
- 如何首次配置postgresql ?
- 数据库性能调优有哪些资源?
- 为什么在c++中声明enum时使用typedef ?