Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

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

DROP TYPE admin_level1;

Возможно ли, что вы на самом деле спрашиваете, как удалить отдельное значение из типа enum? Если это так, вы не можете. Не поддерживается:

Хотя типы 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;

Ответ 2

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

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

SELECT * FROM pg_enum;

Затем проверьте, что поиск значения уникален. Чтобы увеличить уникальность во время удаления rekoru, необходимо передать "enumtypid" в дополнение к "enumlabel".

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

УДАЛИТЬ ИЗ pg_enum en WHERE en.enumtypid = 124 AND en.enumlabel = 'unique';

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

Ответ 3

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

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;

Ответ 4

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

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

Вот пример:

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

Ответ 5

Используйте следующий запрос для удаления значения ENUM из типа 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**'; 

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

Ответ 6

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

Ответ 7

Вы можете использовать ниже запрос

УДАЛИТЬ ИЗ pg_enum WHERE enumlabel = 'moderator';

Ответ 8

Программный способ сделать это заключается в следующем. Подходят те же общие шаги, которые приведены в fooobar.com/questions/148153/..., но они более ручные, чем имели смысл для моих целей (написание миграции вниз по алгоритму). 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;
    

Ответ 9

Невозможно удалить отдельное значение из ENUM, единственное возможное решение - это DROP и воссоздать ENUM с необходимыми значениями.