Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drop a single enum value in postgres

Say I have the following enum:

CREATE TYPE "my_enum" AS ENUM('value1', 'value2', 'value3');

I would like get remove value3. From what I can see in the documentation and in previous threads, I actually have to drop the whole enum and recreate it with the values I want. Something like this:

DROP TYPE IF EXISTS "my_enum";

CREATE TYPE "my_enum" AS ENUM('value1', 'value2');

The issue with that is I have other tables that depend on this enum, so it won't allow me to do so. I get the following message (rightfully so):

ERROR: cannot drop type "my_enum" because other objects depend on it

So my question is how can I remove one of the enums values without dropping the whole thing? I know I can easily add values by just altering:

ALTER TYPE "my_enum" ADD VALUE 'value4';

So I would think I could do something to the equivalent when removing.

Thanks!

like image 387
theJuls Avatar asked Jun 26 '19 15:06

theJuls


People also ask

How do I change enum in PostgreSQL?

Change or delete enum value ALTER TYPE delivery_status RENAME VALUE 'PACKAGING' TO 'PREPARING'; Other than that, PostgreSQL doesn't support changing or deleting specific enum value. The workaround is the same as above: rename old type, create new and correct type, and delete old type.

Does PostgreSQL support enum?

When using PostgreSQL, each ENUM type is registered in the system catalogs and can be used anywhere PostgreSQL expects a type name. Internally, the ENUM values are stored as integers. It is important to realize that each ENUM type in PostgreSQL is registered in the system catalogs.

What is Pg_enum?

The pg_enum catalog contains entries showing the values and labels for each enum type. The internal representation of a given enum value is actually the OID of its associated row in pg_enum .


2 Answers

You have to drop the type, however, you can temporarily alter table(s) containing columns of the type.

Example model:

create type my_enum as enum('apple', 'pear', 'banana');
create table my_table(id serial primary key, my_col my_enum);
insert into my_table (my_col) values
    ('apple'),
    ('pear');

Remove banana from the enum type:

alter table my_table alter my_col type text;
drop type my_enum;
create type my_enum as enum('apple', 'pear');
alter table my_table alter my_col type my_enum using my_col::my_enum;

Check:

select * from my_table;

 id | my_col 
----+--------
  1 | apple
  2 | pear
(2 rows)    
like image 149
klin Avatar answered Oct 11 '22 08:10

klin


Hm, although it is really REALLY not recommended, there is a way to achieve this if you have the rights to do:

SELECT 
    t.typname,
    e.enumlabel,
    e.enumtypid
FROM pg_type t
JOIN pg_enum e ON e.enumtypid = t.oid
WHERE t.typname = '<your enum name>'

This gives you the dbms internal id enumtypid of the enum type.

With this you can do the deletion:

DELETE FROM pg_enum
WHERE enumtypid = <your enumtypid>
    AND enumlabel = '<enum value to delete>'

You have to ensure that you are not using the value anymore before this. Otherwise you table could become corrupt!

like image 27
S-Man Avatar answered Oct 11 '22 07:10

S-Man