List PostgreSQL Enum Types and Their Values with SQL
How to List All Enum Types in a PostgreSQL Database
PostgreSQL supports user-defined enum types — a fixed ordered set of string values stored efficiently as integers. Enums are common in application schemas for columns like status, role, or priority. Once created, their allowed values are managed in the database catalog, not in application code.
Over time, a database can accumulate many enum types, some with values that no longer match what the application uses. This SQL script queries pg_type and pg_enum to list every enum type in the current database along with all of its allowed values.
SQL Script
1SELECT
2 n.nspname AS schema_name,
3 t.typname AS enum_name,
4 e.enumlabel AS enum_value,
5 e.enumsortorder AS sort_order
6FROM
7 pg_type t
8 JOIN pg_enum e
9 ON e.enumtypid = t.oid
10 JOIN pg_namespace n
11 ON n.oid = t.typnamespace
12WHERE
13 n.nspname NOT IN ('pg_catalog', 'information_schema')
14ORDER BY
15 n.nspname,
16 t.typname,
17 e.enumsortorder;
Notes: Works on PostgreSQL 8.3 and later, when pg_enum was introduced. Returns one row per enum value. To see one row per enum type with all values aggregated, use array_agg(e.enumlabel ORDER BY e.enumsortorder).
Code Breakdown
pg_type
The PostgreSQL system catalog table that stores information about every data type — both built-in types and user-defined types. The join to pg_enum implicitly filters to only enum types.
pg_enum
Stores one row for each value of each enum type. Key columns:
enumtypid— the OID of the parent type inpg_typeenumlabel— the text value (e.g.'active','inactive')enumsortorder— a float that defines the display order of values
pg_namespace
Stores schema names. Joined on t.typnamespace = n.oid to resolve the schema each enum type belongs to.
JOIN pg_enum ON e.enumtypid = t.oid
Links each enum value row back to its type. Because only enum types have rows in pg_enum, this join acts as an implicit filter for enum types only.
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
Excludes system schemas. All built-in PostgreSQL types live in pg_catalog. This filter returns only user-defined enums.
ORDER BY schema, type name, sort_order
Groups all values for the same enum together and lists them in the order they were defined, matching the order PostgreSQL uses for comparisons and sorting.
Key Points
- Enum values are case-sensitive.
'Active'and'active'are different values. - The
enumsortordercolumn determines how PostgreSQL sorts and compares enum values. The value defined first is the "smallest". - Enum types are schema-scoped. Two schemas can have different enum types with the same name.
- Adding a new value to an existing enum requires
ALTER TYPE ... ADD VALUE, not a full type recreate.
Insights and Explanations
Enum types offer storage efficiency, enforced value constraints, and natural ordering — but they come with operational tradeoffs:
- Adding values is easy; removing them is not. You can add a new value with
ALTER TYPE name ADD VALUE 'new_value'. But you cannot remove a value without dropping and recreating the type, which requires dropping every column that uses it. - Schema migrations are risky. If your application tries to insert a value that does not exist in the enum, PostgreSQL raises an error. Deploy new enum values to the database before deploying the application code that writes them.
- Enum values have a defined sort order. Queries using
ORDER BYon an enum column sort by declaration order, not alphabetically. This is intentional but surprises developers who expect alphabetical sorting.
To see a compact summary with all values per enum on one line:
1SELECT
2 n.nspname AS schema_name,
3 t.typname AS enum_name,
4 array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values
5FROM
6 pg_type t
7 JOIN pg_enum e ON e.enumtypid = t.oid
8 JOIN pg_namespace n ON n.oid = t.typnamespace
9WHERE
10 n.nspname NOT IN ('pg_catalog', 'information_schema')
11GROUP BY
12 n.nspname,
13 t.typname
14ORDER BY
15 n.nspname,
16 t.typname;
To find which tables and columns use a specific enum type:
1SELECT
2 c.table_schema,
3 c.table_name,
4 c.column_name
5FROM
6 information_schema.columns c
7WHERE
8 c.udt_name = 'your_enum_name'
9ORDER BY
10 c.table_schema,
11 c.table_name,
12 c.column_name;
Additional Considerations
- Permissions: Any user can query
pg_type,pg_enum, andpg_namespace. No superuser privilege is required. - Domains over enums: Some schemas use
CREATE DOMAINinstead ofCREATE TYPE ... AS ENUM. Domains do not appear inpg_enum. Checkpg_typewheretyptype = 'd'to list domains. - Enum OIDs across databases: Enum type OIDs are not shared across databases. The same type name in two databases will have different OIDs.
References
Posts in this series
- How Many Connections Can Your PostgreSQL Database Handle?
- PostgreSQL Backend Connections via pg_stat_database
- Identifying Blocking PostgreSQL Queries using pg_stat_activity
- List PostgreSQL Databases by Size with Access Check
- Assess PostgreSQL Database Sizes Quickly and Easily
- Unveiling Your PostgreSQL Server - A Diagnostic Powerhouse
- Keep Your PostgreSQL Database Clean, Identify Idle Connections
- Query the PostgreSQL Configuration
- PostgreSQL Recovery Monitoring: Essential SQL Insights
- Restart All PostgreSQL Sequences with ALTER SEQUENCE
- Monitor Running Queries in PostgreSQL using pg_stat_activity
- Monitor PostgreSQL Active Sessions with pg_stat_activity
- PostgreSQL Error Handling Settings via pg_settings
- PostgreSQL File Location Settings Query via pg_settings
- PostgreSQL Lock Management Settings via pg_settings
- PostgreSQL Logging Configuration Query via pg_settings
- Monitor PostgreSQL Memory Settings with pg_settings
- PostgreSQL Table Row Count Estimates with SQL
- List PostgreSQL Tables by Size with SQL
- PostgreSQL WAL Settings Query Guide
- PostgreSQL SSL Settings Query Guide
- PostgreSQL Statistics Settings Query Guide
- PostgreSQL Resource Settings Query Guide
- PostgreSQL Replication Settings Query Guide
- PostgreSQL Query Planning Settings Query Guide
- PostgreSQL Preset Options Settings Query Guide
- PostgreSQL Miscellaneous Settings Query Guide
- Count PostgreSQL Sessions by State with SQL
- Kill Idle PostgreSQL Sessions with SQL
- Grant SELECT on All Tables in PostgreSQL
- Identify Insert-Only Tables in PostgreSQL
- Detect Soft Delete Patterns in PostgreSQL
- List PostgreSQL Object Comments with SQL
- List Foreign Key Constraints in PostgreSQL
- List PostgreSQL Enum Types and Their Values with SQL
- List All Views in a PostgreSQL Database with SQL
- Find PostgreSQL Tables Without a Primary Key
- List PostgreSQL Partitioned Tables with SQL