如何删除我在postgresql中创建的枚举类型值?
create type admin_level1 as enum('classifier', 'moderator', 'god');
E.g。我想从列表中删除moderator
。
我似乎无法在文档上找到任何内容。
我正在使用Postgresql 9.3.4。
答案 0 :(得分:116)
DROP TYPE admin_level1;
您是否有可能实际上询问如何从枚举类型中删除单个值?如果是这样,你就不能。 It's not supported:
虽然
enum
类型主要用于静态值集,但是支持向现有枚举类型添加新值以及重命名值(请参阅ALTER TYPE
)。无法从枚举类型中删除现有值,也不能更改此类值的排序顺序,除非丢弃并重新创建枚举类型。
您必须创建没有值的新类型,将旧类型的所有现有用法转换为使用新类型,然后删除旧类型。
E.g。
CREATE TYPE admin_level1 AS ENUM ('classifier', 'moderator');
CREATE TABLE blah (
user_id integer primary key,
power admin_level1 not null
);
INSERT INTO blah(user_id, power) VALUES (1, 'moderator'), (10, 'classifier');
ALTER TYPE admin_level1 ADD VALUE 'god';
INSERT INTO blah(user_id, power) VALUES (42, 'god');
-- .... oops, maybe that was a bad idea
CREATE TYPE admin_level1_new AS ENUM ('classifier', 'moderator');
-- Remove values that won't be compatible with new definition
-- You don't have to delete, you might update instead
DELETE FROM blah WHERE power = 'god';
-- Convert to new type, casting via text representation
ALTER TABLE blah
ALTER COLUMN power TYPE admin_level1_new
USING (power::text::admin_level1_new);
-- and swap the types
DROP TYPE admin_level1;
ALTER TYPE admin_level1_new RENAME TO admin_level1;
答案 1 :(得分:25)
如果要删除枚举类型的项目,则必须在PostgreSQL的系统表上操作。
使用此命令,您可以显示枚举类型的所有项目。
SELECT * FROM pg_enum;
然后检查搜索到的值是否唯一。除了'enumlabel'之外,为了增加rekoru去除过程中的独特性,必须通过'enumtypid'。
此命令删除枚举类型中的条目,其中“唯一”是您的值。
DELETE FROM pg_enum en WHERE en.enumtypid = 124 AND en.enumlabel ='unique';
注意强> 我必须使用我描述的示例,偶然我们为枚举类型添加新值,但我们还没有在数据库中的任何地方使用它。
答案 2 :(得分:19)
写得很好:
http://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/
重命名现有类型
ALTER TYPE status_enum RENAME TO status_enum_old;
创建新类型
CREATE TYPE status_enum AS ENUM('queued', 'running', 'done');
更新列以使用新类型
ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING job_status::text::status_enum;
删除旧类型
DROP TYPE status_enum_old;
答案 3 :(得分:7)
对于那些希望修改枚举值的人来说,重新创建它似乎是唯一可行且安全的解决方案。
它包括临时将枚举列转换为字符串格式,重新创建枚举,然后将字符串列重新转换回枚举类型。
以下是一个例子:
ALTER TABLE your_schema.your_table ALTER COLUMN your_column TYPE varchar(255);
ALTER TABLE your_schema.your_table ALTER COLUMN your_column SET DEFAULT('your_default_enum_value');
DROP TYPE your_schema.your_enum_name;
CREATE TYPE your_schema.your_enum_name AS ENUM ('enum1', 'enum2', 'enum3');
ALTER TABLE your_schema.your_table ALTER your_column DROP DEFAULT;
ALTER TABLE your_schema.your_table ALTER COLUMN your_column TYPE your_schema.your_enum_name USING your_enum_name::your_schema.your_column;
ALTER TABLE your_schema.your_table ALTER COLUMN your_column SET DEFAULT('your_default_enum_value');
答案 4 :(得分:6)
使用以下查询从Postgresql类型中删除ENUM值
DELETE FROM pg_enum
WHERE enumlabel = 'moderator'
AND enumtypid = ( SELECT oid FROM pg_type WHERE typname = 'admin_level1');
只需知道什么类型和价值
DELETE FROM pg_enum
WHERE enumlabel = 'ENUM_VALUE'
AND enumtypid = ( SELECT oid FROM pg_type WHERE typname = 'ENUM_TYPE')
您应该将现有值更改为其他值。为此,如果您需要添加新值,请使用:
ALTER TYPE **ENUM_TYPE** ADD VALUE '**ENUM_VALUE2**';
删除前,请将类型值更新为新类型值或现有值。
答案 5 :(得分:1)
如果您的数据集不是那么大,您可以使用--column-inserts
转储使用文本编辑器编辑转储,删除该值并重新导入转储
答案 6 :(得分:1)
我的解决方案始于这样一个事实,即我在我的场景中没有权限执行 LIMIT
,因为我收到了权限错误。
从其他回复开始,我创建了一个泛型函数,可以用来从枚举中删除单个值,支持更新值释放给定值的使用
DELETE FROM pg_enum
答案 7 :(得分:0)
执行此操作的编程方式如下。相同的一般步骤
https://stackoverflow.com/a/47305844/629272中的值是适当的,但是
就我的目的而言,手册比手册更有意义(编写了一个向下迁移的alembic)。当然,应适当地更改my_type
,my_type_old
和value_to_delete
。
重命名您的类型。
ALTER TYPE my_type RENAME TO my_type_old;
使用旧类型中的值创建新类型,但不包括旧类型 您要删除。
DO $$
BEGIN
EXECUTE format(
'CREATE TYPE my_type AS ENUM (%s)',
(
SELECT string_agg(quote_literal(value), ',')
FROM unnest(enum_range(NULL::my_type_old)) value
WHERE value <> 'value_to_delete'
)
);
END $$;
将所有使用旧类型的现有列更改为使用新列。
DO $$
DECLARE
column_data record;
table_name varchar(255);
column_name varchar(255);
BEGIN
FOR column_data IN
SELECT cols.table_name, cols.column_name
FROM information_schema.columns cols
WHERE udt_name = 'my_type_old'
LOOP
table_name := column_data.table_name;
column_name := column_data.column_name;
EXECUTE format(
'
ALTER TABLE %s
ALTER COLUMN %s
TYPE my_type
USING %s::text::my_type;
',
table_name, column_name, column_name
);
END LOOP;
END $$;
删除旧类型。
DROP TYPE my_type_old;
答案 8 :(得分:0)
v.10中存在相同的问题。 Postgres。 删除需要某些步骤,如果顺序不正确,则甚至有可能将表锁定以进行读取。
编写了一个方便的脚本来删除。已经证明了其性能的数倍。但是,此过程涉及用一个新值替换已删除的值(如果表字段允许,则为NULL。)
要使用,您只需填写3个值。
DO $$
DECLARE
enumTypeName VARCHAR := 'enum_name'; -- VALUE #1, set yor value!
enumOldFieldValue varchar := 'old_enum_value'; -- VALUE #2, enum value which have to be deleted
enumNewFieldValue varchar := null; -- VALUE #3, which new value must be instead of deleted
sql varchar:='';
rec record;
BEGIN
raise info 'Check on old and new enum values.';
IF exists(select * FROM pg_enum -- check existing of OLD enum value
WHERE enumtypid = (select oid from pg_type where typName=cast(enumTypeName as varchar) limit 1) and enumlabel=cast(enumOldFieldValue as varchar))
AND
(exists(select *
FROM pg_enum -- check existing of NEW enum value
WHERE enumtypid = (select oid from pg_type where typName = cast(enumTypeName as varchar) limit 1)
and enumlabel = cast(enumNewFieldValue as varchar))
OR
enumNewFieldValue IS NULL)
THEN
raise info 'Check passed!';
-- selecting all tables with schemas which has column with enum relation
create temporary table tmp_table_names
as SELECT concat(c.table_schema,'.',c.table_name ) as table_name, c.column_name
FROM information_schema.columns c
WHERE c.udt_name = cast(enumTypeName as varchar)
and c.table_schema=c.udt_schema and data_type = 'USER-DEFINED';
-- if we have table(s) that uses such enum
if exists(select * from tmp_table_names)
then
FOR rec in (select table_name, column_name from tmp_table_names) LOOP
sql:= format('UPDATE %1$s set %2$s = %3$L where %2$s=%4$L',rec.table_name, rec.column_name, enumNewFieldValue, enumOldFieldValue);
raise info 'Update by looping: %', sql;
EXECUTE sql;
END LOOP;
end if;
-- just after changing all old values in all tables we can delete old enum value
sql := format('DELETE FROM pg_enum WHERE enumtypid = (select oid from pg_type where typName=%1$L limit 1) and enumlabel=%2$L',enumTypeName,enumOldFieldValue);
raise info 'Delete enum value: %', sql;
EXECUTE sql;
drop table tmp_table_names;
ELSE
raise info 'Old or new enum values is missing.';
end if;
END $$;
答案 9 :(得分:-1)
不可能从ENUM中删除单个值,唯一的解决方案是DROP并使用所需的值重新创建ENUM。