Working with Collations

1. Understanding Collations

ConceptDetail
CollationSort/compare rules for text
Providerlibc (OS) or ICU (preferred)
Localeen_US.UTF-8, en-US-x-icu, ...
DeterministicEqual bytes ⇔ equal strings (default true)

2. Listing Available Collations

SELECT collname, collprovider, collcollate, collctype
  FROM pg_collation ORDER BY collname;

3. Setting Database Collation

CREATE DATABASE shop
   ENCODING 'UTF8' LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8'
   ICU_LOCALE 'en-US' LOCALE_PROVIDER icu TEMPLATE template0;

4. Using COLLATE Clause in Query

SELECT name FROM customers
 ORDER BY name COLLATE "de-DE-x-icu";

5. Using COLLATE in Index

CREATE INDEX customers_name_de ON customers (name COLLATE "de-DE-x-icu");

6. Creating Custom Collation

CREATE COLLATION case_insens (provider = icu, locale = 'und-u-ks-level2', deterministic = false);
SELECT 'AbC' = 'abc' COLLATE case_insens;     -- true

7. Using ICU Collations

CREATE COLLATION numeric_aware (provider = icu, locale = 'en-u-kn-true');
SELECT 'item10' < 'item2' COLLATE numeric_aware;   -- false (natural sort)

8. Using Libc Collations

CREATE COLLATION german (provider = libc, locale = 'de_DE.UTF-8');
Warning: libc collations change with glibc upgrades — silently corrupts B-tree indexes. Use ICU.

9. Using Case-Insensitive Collations

CREATE COLLATION ci (provider=icu, locale='und-u-ks-level2', deterministic=false);
CREATE TABLE users (email text COLLATE ci UNIQUE);

10. Understanding Collation Impact on Indexes

Note: Index uses column collation. Querying with a different COLLATE in WHERE bypasses the index unless an additional index on that collation exists.

11. Understanding Collation Impact on ORDER BY

SELECT name FROM customers ORDER BY name;                       -- column collation
SELECT name FROM customers ORDER BY name COLLATE "C";           -- byte order

12. Altering Column Collation

ALTER TABLE customers ALTER COLUMN name TYPE text COLLATE "en-US-x-icu";
REINDEX TABLE customers;     -- mandatory after collation change