List PostgreSQL Collations with pg_collation and ICU
List Collations Available in PostgreSQL
pg_collation is the system catalog that holds every collation a database can use — the sort-and-compare rules behind ORDER BY, DISTINCT, comparison operators and text indexes. One query against it shows each collation's name, the library that implements it, and the locale it maps to, which is the first thing to check when text sorts differently on two servers.
Purpose and Overview
A collation decides how text is ordered and compared. In PostgreSQL the collation feature "allows specifying the sort order and character classification behavior of data per-column, or even per-operation," so one database can hold columns that sort by different rules.
Collations come from three providers. libc collations come from the operating system's locales, icu collations come from the ICU library when PostgreSQL is built with it, and from PostgreSQL 17 there is also a builtin provider. Because libc and icu collations take their rules from libraries outside PostgreSQL, the sort order depends on which library and version the server has.
The queries below list every collation with its provider and locale, narrow the list to one locale, and show which collation the current database uses by default. That covers the usual questions: what is available, which one should a new column use, and why two environments disagree.
Sample Code
List all collations with their provider and locale:
1SELECT
2 collname AS collation_name,
3 pg_catalog.pg_get_userbyid(collowner) AS owner,
4 collprovider AS provider,
5 collencoding AS encoding,
6 collcollate AS lc_collate,
7 collctype AS lc_ctype
8FROM pg_catalog.pg_collation
9ORDER BY collname;
Find the collations for one locale (PostgreSQL 17 and later):
1SELECT collname, collprovider, collcollate, collctype, colllocale
2FROM pg_catalog.pg_collation
3WHERE collcollate ILIKE '%en_US%'
4 OR colllocale ILIKE '%en_US%'
5ORDER BY collname;
Check the current database's default collation:
1SELECT datname, datcollate, datctype
2FROM pg_database
3WHERE datname = current_database();
Notes: The first and third queries run on PostgreSQL 10 and later. The locale query needs PostgreSQL 17 or later; on 15 and 16 replace colllocale with colliculocale, and on 14 and earlier drop that column and the OR line. Adjust the '%en_US%' pattern to the locale you need.
Code Breakdown
The main query reads one row per collation from pg_collation and turns the owner OID into a role name.
The pg_collation columns
The pg_collation catalog defines each column. collprovider is the "provider of the collation: d = database default, b = builtin, c = libc, i = icu." collencoding is the "encoding in which the collation is applicable, or -1 if it works for any encoding." collcollate and collctype hold the LC_COLLATE and LC_CTYPE values, but only for libc collations: "if the provider is not libc, collcollate is NULL and colllocale is used instead."
The owner lookup
pg_get_userbyid(collowner) converts the owner's OID into a role name.
Why the locale query checks two columns
Because ICU and builtin collations leave collcollate empty, a search on collcollate alone finds only libc collations. The OR colllocale condition catches the rest. In PostgreSQL 17, colllocale is the "collation provider locale name for this collation object"; in 15 and 16 the same role was played by colliculocale, which covered ICU only.
The database default
pg_database.datcollate and datctype show the collation and character classification the database was created with. Every text column that does not name a collation uses this default.
Key Collation Providers
C and POSIX
C and POSIX are equivalent. They "sort by byte values rather than natural language order, and only the ASCII letters A through Z are treated as letters." The documentation describes their behavior as "efficient and stable across all versions for a given database encoding," which makes C a safe choice for identifiers and codes where alphabetical order for people does not matter.
libc
libc collations use the operating system's locales, such as en_US.utf8. They use "the locales provided by the operating system C library" — the same locales most other tools on that server use — so their order follows that library.
ICU
ICU collations are named "in BCP 47 language tag format, with a private use extension -x-icu appended, to distinguish them from libc locales" — for example de-x-icu for German, or und-x-icu, the ICU root locale ("undefined"). ICU behavior can change when PostgreSQL is built against a different ICU version.
Deterministic and nondeterministic
A deterministic collation "considers strings to be equal only if they consist of the same byte sequence." A nondeterministic one may treat different byte sequences as equal — for example for case-insensitive comparison. The documentation warns of a performance cost and notes that B-tree indexes cannot use deduplication with a nondeterministic collation. Create one with CREATE COLLATION and deterministic = false.
Practical Applications
Diagnosing a sort-order difference
When the same ORDER BY returns rows in a different order on two servers, compare datcollate on both databases and the column's collation. If they match, compare the provider and collversion, the provider-specific version of the collation: libc and ICU rules come from the server's libraries.
Choosing a collation for a new column
Run the locale query to see what is installed, then set the column's collation explicitly, for example name text COLLATE "de-x-icu". A COLLATE clause can also be added to a single query, such as ORDER BY name COLLATE "C", without changing the column.
Explaining a collation error
When an expression combines inputs with different collations, PostgreSQL applies its derivation rules: "If any input expression has an explicit collation derivation, then all explicitly derived collations among the input expressions must be the same, otherwise an error is raised." Listing the collations involved shows which COLLATE clause to add or remove.
Comparing with the SQL-standard view
information_schema.collations lists the same collations with only four columns — collation_catalog, collation_schema, collation_name and pad_attribute. The last is "always NO PAD," since PostgreSQL does not support PAD SPACE. For provider and locale details, use pg_collation.
Version Compatibility
pg_collation first appears in the PostgreSQL 9.1 documentation. collprovider was added in PostgreSQL 10, together with ICU support, and collisdeterministic in PostgreSQL 12, when nondeterministic collations arrived.
The locale column has changed twice. PostgreSQL 15 and 16 have colliculocale, which holds the ICU locale. PostgreSQL 17 replaced it with colllocale, which covers both ICU and the new builtin provider. Queries written for one version will fail on the other, so check the server version before reusing a script across clusters.
ICU itself became a default part of source builds: in current releases you build without it using --without-icu, while PostgreSQL 15 and earlier needed --with-icu to include it. Check for i in collprovider to confirm a server has it.
Best Practices
- Set collations explicitly on columns that need a specific sort order — do not rely on whatever the server's default locale happens to be.
- Use
Cfor codes and identifiers — byte order is stable across versions for a given encoding. - Record each collation's provider and
collversionbefore an OS or ICU upgrade — the rules come from libraries outside PostgreSQL. - Prefer ICU for consistent natural-language sorting across platforms — and keep the ICU version in mind when you upgrade.
- Test nondeterministic collations before production — they cost performance and block some index and pattern-matching features.
References
- PostgreSQL: Collation Support — providers, C and POSIX, ICU naming, derivation rules and nondeterministic collations
- PostgreSQL: pg_collation — every column of the catalog, including
collproviderandcolllocale - PostgreSQL: CREATE COLLATION — creating ICU, libc and nondeterministic collations
- PostgreSQL: information_schema.collations — the SQL-standard view and
pad_attribute - PostgreSQL: Building and Installation with Autoconf and Make — the
--without-icubuild option - andyatkinson/pg_scripts: list_collations.sql — original seed script
Posts in this series
- How Many Connections Can Your PostgreSQL Database Handle?
- PostgreSQL Backend Connections via pg_stat_database
- pg_blocking_pids — Find Blocking Queries in PostgreSQL
- 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
- pg_is_in_recovery — Monitor PostgreSQL Standby Status
- ALTER SEQUENCE RESTART WITH in PostgreSQL — Examples
- 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
- Inspect PostgreSQL Lock Management Settings with 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
- log_parser_stats, log_planner_stats, log_executor_stats — PostgreSQL
- PostgreSQL SSL 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 — with Examples
- pg_stat_user_tables — Find 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
- List All Schemas in Your PostgreSQL Database
- pg_stat_database — Query PostgreSQL Database Statistics
- List PostgreSQL Roles and Their Privileges
- Scrubbing Email PII in PostgreSQL for GDPR Compliance
- List Installed Extensions in PostgreSQL
- List PostgreSQL Collations with pg_collation and ICU
- PostgreSQL Replica Identity for Logical Replication
- Monitor PostgreSQL Vacuum Progress with pg_stat_progress_vacuum
- Monitor PostgreSQL Wait Events Using pg_stat_activity
- Monitor PostgreSQL Replication Lag with pg_stat_replication
- List PostgreSQL Wait Events with the pg_wait_events View
- PostgreSQL Column-Level Permissions Audit Query
- List All PostgreSQL Triggers with Their State
- timestamptz and tzdata: Avoid Shifted PostgreSQL Timestamps
- Inspect PostgreSQL Sequences with the pg_sequences View
- List PostgreSQL Functions with pg_proc
- Query PostgreSQL Tablespace Info with pg_tablespace
- Audit PostgreSQL Authentication with pg_hba_file_rules
- List PostgreSQL Materialized Views with pg_matviews
- Audit Row-Level Security Policies with pg_policies