Как удалить значение типа перечисления в 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
, следует, конечно, изменить соответствующим образом.
-
переименовать свой тип.
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;
короче говоря, невозможно удалить отдельное значение из перечисления, единственное возможное решение-удалить и воссоздать перечисление с необходимыми значениями.