Как удалить значение типа перечисления в postgres?

Как удалить значение типа перечисления, которое я создал в postgresql?

create type admin_level1 as enum('classifier', 'moderator', 'god');

например. Я хочу удалить moderator из списка.

Я ничего не могу найти в документах.

Я использую Postgresql 9.3.4.

8 ответов


удалить (капли) перечислимыми типами, как и любой другой тип, с DROP TYPE:

DROP TYPE admin_level1;

возможно ли, что вы на самом деле спрашиваете о том, как удалить значение из перечислимого типа? Если так, то ты не можешь. Он не поддерживается. Необходимо создать новый тип без значения, преобразовать все существующие виды использования старого типа в новый тип, а затем удалить старый тип.

Э. Г.

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;

Если вы хотите удалить элемент типа перечисления, вы должны работать с системной таблицей PostgreSQL.

с помощью этой команды можно отобразить все элементы перечисления типа.

выберите * из pg_enum;

затем проверьте, что искомое значение уникально. Для увеличения уникальности при удалении рекору необходимо передать 'enumtypid' в дополнение к'enumlabel'.

эта команда удаляет запись в типе перечисления, где 'unique' является вашим значение.

удалить из pg_enum en где en.enumtypid=124 и en.enumlabel= 'уникальный';

Примечание Пример, который я описал, должен использоваться, когда случайно мы добавляем новое значение к типу перечисления, и все же мы не использовали его нигде в базе данных.


для тех, кто хочет изменить значения перечисления, воссоздание его кажется единственным жизнеспособным и безопасным решением.

Он состоит в временном преобразовании столбца перечисления в строковый формат, воссоздании перечисления и повторном преобразовании столбца строки обратно в тип перечисления.

вот пример:

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');

очень хорошо написано здесь:

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;

используйте следующий запрос для удаления значения перечисления из типа Postgresql

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**'; 

перед удалением обновите значение типа до нового значения типа или существующего значения.


если ваш набор данных не такой большой, вы можете сбросить его с помощью --column-inserts отредактируйте дамп с помощью текстового редактора, удалите значение и повторно импортируйте дамп


программный способ сделать это следующим образом. Те же общие шаги, что и заданные в https://stackoverflow.com/a/47305844/629272 соответствующие, но те более ручное, чем имело смысл для моих целей (запись миграции перегонного куба). my_type, my_type_old и value_to_delete, следует, конечно, изменить соответствующим образом.

  1. переименовать свой тип.

    ALTER TYPE my_type RENAME TO my_type_old;
    
  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 $$;
    
  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 $$;
    
  4. удалить старый тип.

    DROP TYPE my_type_old;
    

короче говоря, невозможно удалить отдельное значение из перечисления, единственное возможное решение-удалить и воссоздать перечисление с необходимыми значениями.