web-dev-qa-db-ja.com

postgresで列挙型の値を削除するにはどうすればよいですか?

Postgresqlで作成した列挙型の値を削除するにはどうすればよいですか?

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

例えば。リストからmoderatorを削除したい。

ドキュメントには何も見つからないようです。

Postgresql 9.3.4を使用しています。

76
Amjith

DROP TYPE を使用して、他のタイプと同様に列挙型を削除(ドロップ)します。

DROP TYPE admin_level1;

実際に列挙型から個々の値を削除する方法を尋ねている可能性はありますか?もしそうなら、あなたはできません。 サポートされていません

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;
129
Craig Ringer

ここに非常によく書かれています:

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;
26
dnaik

列挙型のアイテムを削除する場合は、PostgreSQLのシステムテーブルを操作する必要があります。

このコマンドを使用すると、すべてのアイテムの列挙型を表示できます。

SELECT * FROM pg_enum;

次に、検索された値が一意であることを確認します。 rekoruの削除中に一意性を高めるには、「enumlabel」に加えて「enumtypid」を渡す必要があります。

このコマンドは、列挙型のエントリを削除します。「一意」はあなたの値です。

pg_enum en WHERE en.enumtypid = 124 AND en.enumlabel = 'unique';から削除

NOTE偶然新しい値を列挙型に追加し、それでもデータベースのどこにも使用していない場合は、説明した例を使用する必要があります。

26
elcudro

列挙値を変更したい人にとっては、それを再作成することが唯一の実行可能で安全な解決策のようです。

一時的に列挙型列を文字列形式に変換し、列挙型を再作成してから、文字列型列を列挙型に再変換します。

以下に例を示します。

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

次のクエリを使用して、PostgresqlタイプからENUM値を削除します

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
Somnath Muluk

データセットがそれほど大きくない場合は、--column-insertsでダンプできます。テキストエディターでダンプを編集し、値を削除して、ダンプを再インポートします。

1
sherpya

これをプログラムで行う方法は次のとおりです。 https://stackoverflow.com/a/47305844/629272 に記載されているのと同じ一般的な手順が適切ですが、これらは私の目的(アレンビックダウンマイグレーションを記述する)に理にかなっているよりも手動です。 my_typemy_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;
    
0
Californian