Altering PostgreSQL columns from one enum to another

Altering the type of a column in postgres from one enum type to another requires an intermediate cast to  text. Additionally, if there is a default value for the field, it cannot be altered and instead must be dropped and re-added as the new type.

Simple case: New type contains all old-type values

In the simple version, the new enum type contains (at least) all of the same labels as the old one. For instance, as with these two:

No default on column

If a table has an old_enum column and we want to turn it into a new_enum one, with no default value in place on the column, we can use the following command:

The USING expression casts the current value of column_name to text, and then to new_enum. This works because every allowed value of the first enum type exists in the second.

With a default value

This case is not significantly more difficult to deal with. If there is a default value on the column, we simply remove it before altering the enum type of the column, and then add a new one when we’re done:

Converting enum labels

A more complicated scenario arises when not all of the old labels appear in the new enum. I’ll assume that there is a mapping from the old ones to the new, at least for every label that is known to appear in a row of the table. If there isn’t, then the conversion is probably not a good idea in the first place.

Consider now an even newer type,

We still want to convert from the old_enum type, but now we also want to map the label ‘a’ to ‘alpha’, and ‘b’ to ‘beta’, while leaving ‘c’ and ‘d’ alone. This can be accomplished by manually applying each required change via a CASE  statement in the USING  expression:

For each record, this statement returns ‘alpha’ or ‘beta’ if the column contains ‘a’ or ‘b’, respectively, or otherwise returns the current value in the column cast as text. The returned value in all cases is then cast to the newer enum type.

5 Comments

    • michael

      Do you mean that the old enum has labels (‘a’, ‘b’, ‘c’) and the new one just has (‘alpha’, ‘beta’), except there are no records that use label ‘c’? Or more simply that you have (‘a’, ‘b’, ‘c’) and want to turn it into (‘a’, ‘b’) because nothing is using ‘c’?

Leave a Reply

Your email address will not be published. Required fields are marked *