Как удалить значение типа перечисления в postgres?
Как удалить значение типа перечисления, которое я создал в postgresql?
create type admin_level1 as enum('classifier', 'moderator', 'god');
например. Я хочу удалить moderator
из списка.
Я не могу найти ничего в документах.
Я использую Postgresql 9.3.4.
Ответы
Ответ 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
, конечно, должны быть изменены соответствующим образом.
-
Переименуйте свой тип.
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;
Ответ 9
Невозможно удалить отдельное значение из ENUM, единственное возможное решение - это DROP и воссоздать ENUM с необходимыми значениями.