Handling PostgreSQL ENUM Types: Fixing Errors When Filtering ENUM Values in Queries

Handling PostgreSQL ENUM Types: Fixing Errors When Filtering ENUM Values in Queries
Photo by Claudio Schwarz / Unsplash

In PostgreSQL, ENUM types are a useful feature that allows developers to define a set of allowed values for a column, adding a layer of data integrity to the database. This guide will focus on an example where filtering ENUM values without the proper type casting causes an error and how to resolve it.

Understanding the Setup

Let’s start by creating an ENUM type for movie ratings, using the standard Motion Picture Association of America (MPAA) ratings:

CREATE TYPE mpaa_rating AS ENUM ('G', 'PG', 'PG-13', 'R', 'NC-17');

Next, we create a movies table that includes a title and a rating, where rating uses the mpaa_rating enum type.

CREATE TABLE movies (
    title VARCHAR(255),
    rating mpaa_rating
);

We then insert some sample movie data:

INSERT INTO movies (title, rating) VALUES
('Mystery Island', 'PG'),
('The Lost Diary', 'R'),
('Galaxy Wars', 'PG-13'),
('Dream Chasers', 'G'),
('Forbidden Planet', 'NC-17');

The Issue: Filtering ENUM Values

Now, let's say you want to query the movies that don’t have an MPAA rating starting with 'PG'. Naturally, you might try to write the query as follows:

SELECT title, rating
FROM movies
WHERE rating NOT ILIKE 'PG%'
GROUP BY title, rating;

This query looks fine at first glance, but it will result in the following error:

psql:commands.sql:21: ERROR:  operator does not exist: mpaa_rating !~~* unknown
LINE 3: WHERE rating NOT ILIKE 'PG%'
                     ^
HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.

Understanding the Error

The error arises because the rating column is of type mpaa_rating (an ENUM type), and PostgreSQL doesn’t automatically allow ENUM values to be used in operations like pattern matching (ILIKE). The database requires a text representation of the ENUM value for such comparisons.

The Solution: Type Casting with ::text

To solve this problem, we need to cast the ENUM type to text. This allows the ENUM values to be treated as plain text, making them compatible with the ILIKE operator.

Here’s the corrected query:

SELECT title, rating
FROM movies
WHERE rating::text NOT ILIKE 'PG%'
GROUP BY title, rating;

In this case, the ::text casts the rating column from its mpaa_rating enum type to a text string. This allows the ILIKE operator to perform a case-insensitive comparison to find movies whose ratings don’t start with PG.

Now the data appear correctly.

      title       | rating 
------------------+--------
 Dream Chasers    | G
 Forbidden Planet | NC-17
 The Lost Diary   | R
(3 rows)

Why the Cast Is Necessary

PostgreSQL ENUM types are stored internally as integers but are displayed as text values. Because of this, operations like pattern matching (ILIKE) or string functions (e.g., LIKE, SUBSTRING) require explicit conversion from ENUM to text.

Without the cast, PostgreSQL does not know how to apply a text-based operation like ILIKE on an ENUM type, hence the error.

Finally

PostgreSQL’s ENUM types are powerful for maintaining strict data integrity, but certain operations like filtering with ILIKE require special handling. By using explicit type casting (::text), you can work around this limitation and filter ENUM values effectively.

In summary:

  • ENUM values must be cast to text when performing text-based operations such as pattern matching (ILIKE).
  • PostgreSQL gives clear error messages, allowing you to resolve type mismatches by adding explicit casts.

This approach ensures that your queries remain flexible and functional while maintaining the benefits of using ENUM types for structured data.

Support Us