Wie lösche ich einen Aufzählungstypwert, den ich in postgresql erstellt habe?
create type admin_level1 as enum('classifier', 'moderator', 'god');
Z.B. Ich möchte moderator
aus der Liste entfernen.
Ich kann anscheinend nichts in den Dokumenten finden.
Ich verwende Postgresql 9.3.4.
Sie löschen (löschen) Aufzählungstypen wie jeden anderen Typ mit DROP TYPE
:
DROP TYPE admin_level1;
Ist es möglich, dass Sie tatsächlich fragen, wie Sie einen einzelnen Wert aus einem Aufzählungstyp entfernenWenn ja, kannst du nicht. Es wird nicht unterstützt :
Obwohl
enum
-Typen hauptsächlich für statische Wertesätze vorgesehen sind, können Sie einem vorhandenen Aufzählungstyp neue Werte hinzufügen und Werte umbenennen (sieheALTER TYPE
). Vorhandene Werte können nicht aus einem Aufzählungstyp entfernt werden, und die Sortierreihenfolge dieser Werte kann nicht geändert werden, ohne dass der Aufzählungstyp gelöscht und erneut erstellt wird.
Sie müssen einen neuen Typ ohne den Wert erstellen, alle vorhandenen Verwendungen des alten Typs in den neuen Typ konvertieren und dann den alten Typ löschen.
Z.B.
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;
Wenn Sie ein Element des Aufzählungstyps löschen möchten, müssen Sie die Systemtabelle von PostgreSQL verwenden.
Mit diesem Befehl können Sie alle Elementtypen anzeigen.
SELECT * FROM pg_enum;
Überprüfen Sie dann, ob der Wert eindeutig ist. Um die Eindeutigkeit während der Entfernung von rekoru zu erhöhen, muss zusätzlich zu „enumlabel“ „enumtypid“ übergeben werden.
Dieser Befehl entfernt den Eintrag im Aufzählungstyp, wobei "unique" Ihr Wert ist.
DELETE FROM pg_enum de WO en.enumtypid = 124 AND en.enumlabel = 'unique';
NOTE Das Beispiel, das ich beschrieben habe, muss verwendet werden, wenn wir zufällig einen neuen Wert zum Aufzählungstyp hinzufügen und ihn jedoch nirgendwo in der Datenbank verwendet haben.
Sehr gut hier geschrieben:
http://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/
den vorhandenen Typ umbenennen
ALTER TYPE status_enum RENAME TO status_enum_old;
den neuen Typ erstellen
CREATE TYPE status_enum AS ENUM('queued', 'running', 'done');
die Spalten aktualisieren, um den neuen Typ zu verwenden
ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING job_status::text::status_enum;
entferne den alten Typ
DROP TYPE status_enum_old;
Für diejenigen, die die Aufzählungswerte ändern möchten, scheint die Neuformulierung die einzige praktikable und sichere Lösung zu sein.
Sie besteht darin, die Enumenspalte vorübergehend in ein Stringformat zu konvertieren, die Enumeration neu zu erstellen und dann die Stringspalte wieder in den Enummentyp zu konvertieren.
Hier ist ein Beispiel:
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');
Verwenden Sie die folgende Abfrage, um den ENUM-Wert aus dem Postgresql-Typ zu löschen
DELETE FROM pg_enum
WHERE enumlabel = 'moderator'
AND enumtypid = ( SELECT oid FROM pg_type WHERE typname = 'admin_level1');
Nur Infos zum Typ und Wert
DELETE FROM pg_enum
WHERE enumlabel = 'ENUM_VALUE'
AND enumtypid = ( SELECT oid FROM pg_type WHERE typname = 'ENUM_TYPE')
Sie sollten vorhandene Werte in andere ändern. Wenn Sie einen neuen Wert hinzufügen müssen, verwenden Sie:
ALTER TYPE **ENUM_TYPE** ADD VALUE '**ENUM_VALUE2**';
Aktualisieren Sie vor dem Löschen den Typwert auf einen neuen Typwert oder einen vorhandenen Wert.
wenn Ihr Dataset nicht so groß ist, können Sie mit --column-inserts
einen Dump mit einem Texteditor bearbeiten, den Wert entfernen und den Dump erneut importieren
Der programmatische Weg dazu ist wie folgt. Die gleichen allgemeinen Schritte wie angegebenIn https://stackoverflow.com/a/47305844/629272 sind angemessen, aber diese sind __ ). my_type
, my_type_old
und value_to_delete
sollten natürlich entsprechend geändert werden.
Benennen Sie Ihren Typ um.
ALTER TYPE my_type RENAME TO my_type_old;
Erstellen Sie einen neuen Typ mit den Werten Ihres alten Typs, ausgenommen denjenigen Sie möchten löschen.
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 $$;
Ändern Sie alle vorhandenen Spalten, die den alten Typ verwenden, um den neuen zu verwenden.
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 $$;
Löschen Sie den alten Typ.
DROP TYPE my_type_old;