如何删除postgres中的枚举类型值?

Amj*_*ith 86 postgresql enums

如何删除我在postgresql中创建的枚举类型值?

create type admin_level1 as enum('classifier', 'moderator', 'god');
Run Code Online (Sandbox Code Playgroud)

我想moderator从列表中删除.

我似乎无法在文档上找到任何内容.

我正在使用Postgresql 9.3.4.

Cra*_*ger 147

您删除(删除)任何其他类型的枚举类型,使用DROP TYPE:

DROP TYPE admin_level1;
Run Code Online (Sandbox Code Playgroud)

您是否有可能实际上询问如何从枚举类型中删除单个值?如果是这样,你就不能.它不受支持:

虽然enum类型主要用于静态值集,但是支持向现有枚举类型添加新值以及重命名值(请参阅参考资料ALTER TYPE).无法从枚举类型中删除现有值,也不能更改此类值的排序顺序,除非删除并重新创建枚举类型.

您必须创建没有值的新类型,将旧类型的所有现有用法转换为使用新类型,然后删除旧类型.

例如

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;
Run Code Online (Sandbox Code Playgroud)

  • @RomanPoelinov 直接操作目录,风险自负。postgres 不支持本地删除枚举值是有原因的。与不受支持和不安全的目录黑客相比,这“不正确”如何? (5认同)
  • 这太棒了!这样我就成功解决了 Alembic 迁移问题。我无法添加新的枚举类型,因为“(psycopg2.InternalError) ALTER TYPE ... ADD 无法在事务块内运行” (3认同)
  • 老实说,我不明白为什么选择这个答案。这个答案不正确!您可以从 pg_enum 中删除具有指定标签的值。 (2认同)

小智 29

写得很好:

http://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/

重命名现有类型

ALTER TYPE status_enum RENAME TO status_enum_old;
Run Code Online (Sandbox Code Playgroud)

创建新类型

CREATE TYPE status_enum AS ENUM('queued', 'running', 'done');
Run Code Online (Sandbox Code Playgroud)

更新列以使用新类型

ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING job_status::text::status_enum;
Run Code Online (Sandbox Code Playgroud)

删除旧类型

DROP TYPE status_enum_old;
Run Code Online (Sandbox Code Playgroud)

  • 请注意,如果在约束中使用该列,您可能会在“<>”上收到“运算符不存在”错误。我必须删除使用该列的检查约束,修改该字段,然后重新添加约束。 (2认同)

elc*_*dro 25

如果要删除枚举类型的项,则必须在PostgreSQL的系统表上运行.

使用此命令,您可以显示枚举类型的所有项目.

SELECT*FROM pg_enum;

然后检查搜索到的值是否唯一.除了'enumlabel'之外,为了增加rekoru去除期间的独特性,必须通过'enumtypid'.

此命令将删除枚举类型中的条目,其中"unique"是您的值.

DELETE FROM pg_enum en WHERE en.enumtypid = 124 AND en.enumlabel ='unique';

注意 我必须使用我描述的示例,偶然我们为枚举类型添加新值,但我们还没有在数据库中的任何地方使用它.

  • 这是一个非常危险的操作**,但是如果你知道你在做什么,那么从枚举类型中删除一个值非常快速和简洁.首先,确保没有表使用您要删除的枚举值.如果你不这样做,你将*严重破坏所有引用枚举值的表(例如,从这样的表中选择将返回`错误:枚举的内部值无效`并产生*NO*结果.) (17认同)
  • 没错,这是应该考虑的最重要的方面.我必须使用我描述的示例,偶然我们为枚举类型添加新值,但我们还没有在数据库中的任何地方使用它. (5认同)
  • 请不要太吓人。只要确保他们尽最大努力清理所有相关表中的值,并且他们**在枚举删除操作之前执行完整的数据库转储(使用pg_dumpall)。**因此,如果表损坏,他们可以从转储中手动恢复它。 (2认同)

sve*_*ux2 8

对于那些希望修改枚举值的人来说,重新创建它似乎是唯一可行且安全的解决方案.

它包括临时将枚举列转换为字符串格式,重新创建枚举,然后将字符串列重新转换回枚举类型.

这是一个例子:

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');
Run Code Online (Sandbox Code Playgroud)


Som*_*luk 6

使用以下查询从Postgresql类型中删除ENUM值

DELETE FROM pg_enum
WHERE enumlabel = 'moderator'
AND enumtypid = ( SELECT oid FROM pg_type WHERE typname = 'admin_level1');
Run Code Online (Sandbox Code Playgroud)

只需知道什么类型和价值

DELETE FROM pg_enum
WHERE enumlabel = 'ENUM_VALUE'
AND enumtypid = ( SELECT oid FROM pg_type WHERE typname = 'ENUM_TYPE')
Run Code Online (Sandbox Code Playgroud)

您应该将现有值更改为其他值.为此,如果您需要添加新值,请使用:

ALTER TYPE **ENUM_TYPE** ADD VALUE '**ENUM_VALUE2**'; 
Run Code Online (Sandbox Code Playgroud)

在删除之前,将类型值更新为新类型值或现有值.

  • 如上所述(/sf/ask/1806771221/#comment53091393_32374411)这是*非常危险*。 (3认同)

Cal*_*ian 5

执行此操作的编程方法如下。/sf/answers/3311409111/中给出的相同一般步骤是合适的,但这些步骤对于我的目的(编写 alembic 向下迁移)来说更加手动,而不是有意义。my_typemy_type_old、 、value_to_delete、 当然应该适当改变。

  1. 重命名您的类型。

    ALTER TYPE my_type RENAME TO my_type_old;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用旧类型中的值(不包括要删除的值)创建一个新类型。

    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 $$;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将使用旧类型的所有现有列更改为使用新类型。

    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 $$;
    
    Run Code Online (Sandbox Code Playgroud)
  4. 删除旧类型。

    DROP TYPE my_type_old;
    
    Run Code Online (Sandbox Code Playgroud)