¿Cómo eliminar un valor de tipo de enumeración en postgres?

Resuelto Amjith asked hace 10 años • 10 respuestas

¿Cómo elimino un valor de tipo de enumeración que creé en postgresql?

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

Por ejemplo, quiero eliminarlo moderatorde la lista.

Parece que no puedo encontrar nada en los documentos.

Estoy usando Postgresql 9.3.4.

Amjith avatar Sep 12 '14 21:09 Amjith
Aceptado

Elimina (elimina) tipos de enumeración como cualquier otro tipo, con DROP TYPE:

DROP TYPE admin_level1;

¿Es posible que en realidad esté preguntando cómo eliminar un valor individual de un tipo de enumeración ? Si es así, no puedes. No es compatible :

Aunque enumlos tipos están destinados principalmente a conjuntos estáticos de valores, existe soporte para agregar nuevos valores a un tipo de enumeración existente y para cambiar el nombre de los valores (consulte ALTER TYPE). Los valores existentes no se pueden eliminar de un tipo de enumeración, ni se puede cambiar el orden de dichos valores, salvo eliminar y volver a crear el tipo de enumeración.

Debe crear un nuevo tipo sin el valor, convertir todos los usos existentes del tipo anterior para usar el nuevo tipo y luego eliminar el tipo anterior.

P.ej

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;
Craig Ringer avatar Sep 12 '2014 16:09 Craig Ringer

Muy bien escrito aquí:

http://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/

cambiar el nombre del tipo existente

ALTER TYPE status_enum RENAME TO status_enum_old;

crear el nuevo tipo

CREATE TYPE status_enum AS ENUM('queued', 'running', 'done');

actualizar las columnas para usar el nuevo tipo

ALTER TABLE job ALTER COLUMN job_status TYPE status_enum USING job_status::text::status_enum;

eliminar el tipo antiguo

DROP TYPE status_enum_old;

Posibles errores y solución de problemas:

  • invalid input value for enum {enum name}: "{some value}"- Una o más filas tienen un valor ( "{some value}") que no está en su nuevo tipo. Debe manejar estas filas antes de poder actualizar el tipo de columna.
  • default for column "{column_name}" cannot be cast automatically to type {enum_name}- El valor predeterminado de la columna no está en su nuevo tipo. Debe cambiar o eliminar el valor predeterminado de la columna antes de poder actualizar el tipo de columna. Gracias a Philipp por esta incorporación.
  • cannot alter type of a column used by a view or rule- Todas las vistas y reglas que utilizan la columna deben eliminarse antes de poder ejecutar ALTER y luego volver a crearlas. Hay formas de hacerlo automáticamente.
dnaik avatar Nov 15 '2017 11:11 dnaik

Esta es una operación muy peligrosa . Debe asegurarse de que ninguna tabla utilice el valor de enumeración que desea eliminar. Si no lo hace, romperá gravemente todas las tablas que hacen referencia al valor de enumeración.

Si desea eliminar un elemento de tipo enumeración, debe operar en la tabla del sistema de PostgreSQL.

Con este comando, puede mostrar todos los elementos del tipo de enumeración.

SELECT * FROM pg_enum;

Luego verifique que el valor buscado sea único. Para aumentar la unicidad durante la eliminación de rekoru se debe pasar 'enumtypid' además de 'enumlabel'.

Este comando elimina la entrada en el tipo de enumeración, donde "único" es su valor.

DELETE FROM pg_enum en WHERE en.enumtypid=124 AND en.enumlabel='unique';

Nota : este comando no debe usarse si 'unique'se usa en cualquier lugar de la base de datos.

elcudro avatar Sep 03 '2015 11:09 elcudro