Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8068049
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 5, 20262026-06-05T12:31:52+00:00 2026-06-05T12:31:52+00:00

In Microsoft SQL Server, it’s possible to specify an accent insensitive collation (for a

  • 0

In Microsoft SQL Server, it’s possible to specify an “accent insensitive” collation (for a database, table or column), which means that it’s possible for a query like

SELECT * FROM users WHERE name LIKE 'João'

to find a row with a Joao name.

I know that it’s possible to strip accents from strings in PostgreSQL using the unaccent_string contrib function, but I’m wondering if PostgreSQL supports these “accent insensitive” collations so the SELECT above would work.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-05T12:31:53+00:00Added an answer on June 5, 2026 at 12:31 pm

    Update for Postgres 12 or later

    Postgres 12 adds nondeterministic ICU collations, enabling case-insensitive and accent-insensitive grouping and ordering. The manual:

    ICU locales can only be used if support for ICU was configured when PostgreSQL was built.

    If so, this works for you:

    CREATE COLLATION ignore_accent (provider = icu, locale = 'und-u-ks-level1-kc-true', deterministic = false);
    
    CREATE INDEX users_name_ignore_accent_idx ON users(name COLLATE ignore_accent);
    
    SELECT * FROM users WHERE name = 'João' COLLATE ignore_accent;
    

    fiddle

    Read the manual for details.
    This blog post by Laurenz Albe may help to understand.

    But ICU collations also have drawbacks. The manual:

    […] they also have some drawbacks. Foremost, their use leads to a
    performance penalty. Note, in particular, that B-tree cannot use
    deduplication with indexes that use a nondeterministic collation.
    Also, certain operations are not possible with nondeterministic
    collations, such as pattern matching operations. Therefore, they
    should be used only in cases where they are specifically wanted.

    My "legacy" solution is typically still superior:

    For all versions

    Use the unaccent module for that – which is completely different from what you are linking to.

    unaccent is a text search dictionary that removes accents (diacritic
    signs) from lexemes.

    Install once per database with:

    CREATE EXTENSION unaccent;
    

    If you get an error like:

    ERROR: could not open extension control file
    "/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory
    

    Install the contrib package on your database server like instructed in this related answer:

    • Error when creating unaccent extension on PostgreSQL

    Among other things, it provides the function unaccent() you can use with your example (where LIKE seems not needed).

    SELECT *
    FROM   users
    WHERE  unaccent(name) = unaccent('João');
    

    Index

    To use an index for that kind of query, create an index on the expression. However, Postgres only accepts IMMUTABLE functions for indexes. If a function can return a different result for the same input, the index could silently break.

    unaccent() only STABLE not IMMUTABLE

    Unfortunately, unaccent() is only STABLE, not IMMUTABLE. According to this thread on pgsql-bugs, this is due to three reasons:

    1. It depends on the behavior of a dictionary.
    2. There is no hard-wired connection to this dictionary.
    3. It therefore also depends on the current search_path, which can change easily.

    Some tutorials on the web instruct to just alter the function volatility to IMMUTABLE. This brute-force method can break under certain conditions.

    Others suggest a simple IMMUTABLE wrapper function (like I did myself in the past).

    There is an ongoing debate whether to make the variant with two parameters IMMUTABLE which declares the used dictionary explicitly. Read here or here.

    Another alternative would be this module with an IMMUTABLE unaccent() function by Musicbrainz, provided on Github. Haven’t tested it myself. I think I have come up with a better idea:

    Best for now

    This approach is more efficient than other solutions floating around, and safer.
    Create an IMMUTABLE SQL wrapper function executing the two-parameter form with hard-wired, schema-qualified function and dictionary.

    Since nesting a non-immutable function would disable function inlining, base it on a copy of the C-function, (fake) declared IMMUTABLE as well. Its only purpose is to be used in the SQL function wrapper. Not meant to be used on its own.

    The sophistication is needed as there is no way to hard-wire the dictionary in the declaration of the C function. (Would require to hack the C code itself.) The SQL wrapper function does that and allows both function inlining and expression indexes.

    CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
      RETURNS text
      LANGUAGE c IMMUTABLE PARALLEL SAFE STRICT AS
    '$libdir/unaccent', 'unaccent_dict';
    

    Then:

    CREATE OR REPLACE FUNCTION public.f_unaccent(text)
      RETURNS text
      LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
    $func$
    SELECT public.immutable_unaccent(regdictionary 'public.unaccent', $1)
    $func$;
    

    In Postgres 14 or later, an SQL-standard function is slightly cheaper, yet. Using the short form for a single statement:

    CREATE OR REPLACE FUNCTION public.f_unaccent(text)
      RETURNS text
      LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT
    RETURN public.immutable_unaccent(regdictionary 'public.unaccent', $1);
    

    See:

    • What does BEGIN ATOMIC mean in a PostgreSQL SQL function / procedure?

    Drop PARALLEL SAFE from both functions for Postgres 9.5 or older.

    public being the schema where you installed the extension (public is the default).

    The explicit type declaration (regdictionary) defends against hypothetical attacks with overloaded variants of the function by malicious users.

    Previously, I advocated a wrapper function based on the STABLE function unaccent() shipped with the unaccent module. That disabled function inlining. This version executes ten times faster than the simple wrapper function I had here earlier.
    And that was already twice as fast as the first version which added SET search_path = public, pg_temp to the function – until I discovered that the dictionary can be schema-qualified, too. Still (Postgres 12) not too obvious from documentation.

    If you lack the necessary privileges to create C functions, you are back to the second best implementation: An IMMUTABLE function wrapper around the STABLE unaccent() function provided by the module:

    CREATE OR REPLACE FUNCTION public.f_unaccent(text)
      RETURNS text
      LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
    $func$
    SELECT public.unaccent('public.unaccent', $1)  -- schema-qualify function and dictionary
    $func$;
    

    Finally, the expression index to make queries fast:

    CREATE INDEX users_unaccent_name_idx ON users(public.f_unaccent(name));
    

    Remember to recreate indexes involving this function after any change to function or dictionary, like an in-place major release upgrade that would not recreate indexes. Recent major releases all had updates for the unaccent module.

    Adapt queries to match the index (so the query planner will use it):

    SELECT * FROM users
    WHERE  f_unaccent(name) = f_unaccent('João');
    

    We don’t need the function in the expression to the right of the operator. There we can also supply unaccented strings like 'Joao' directly.

    The faster function does not translate to much faster queries using the expression index. Index look-ups operate on pre-computed values and are very fast either way. But index maintenance and queries not using the index benefit. And access methods like bitmap index scans may have to recheck values in the heap (the main relation), which involves executing the underlying function. See:

    • "Recheck Cond:" line in query plans with a bitmap index scan

    Security for client programs has been tightened with Postgres 10.3 / 9.6.8 etc. You need to schema-qualify function and dictionary name as demonstrated when used in any indexes. See:

    • ‘text search dictionary “unaccent” does not exist’ entries in postgres log, supposedly during automatic analyze

    Ligatures

    In Postgres 9.5 or older ligatures like ‘Œ’ or ‘ß’ have to be expanded manually (if you need that), since unaccent() always substitutes a single letter:

    SELECT unaccent('Œ Æ œ æ ß');
    
    unaccent
    ----------
    E A e a S
    

    You will love this update to unaccent in Postgres 9.6:

    Extend contrib/unaccent‘s standard unaccent.rules file to handle all
    diacritics known to Unicode, and expand ligatures correctly (Thomas
    Munro, Léonard Benedetti)

    Bold emphasis mine. Now we get:

    SELECT unaccent('Œ Æ œ æ ß');
    
    unaccent
    ----------
    OE AE oe ae ss
    

    Pattern matching

    For LIKE or ILIKE with arbitrary patterns, combine this with the module pg_trgm in PostgreSQL 9.1 or later. Create a trigram GIN (typically preferable) or GIST expression index. Example for GIN:

    CREATE INDEX users_unaccent_name_trgm_idx ON users
    USING gin (f_unaccent(name) gin_trgm_ops);
    

    Can be used for queries like:

    SELECT * FROM users
    WHERE  f_unaccent(name) LIKE ('%' || f_unaccent('João') || '%');
    

    GIN and GIST indexes are more expensive (to maintain) than plain B-tree:

    • Difference between GiST and GIN index

    There are simpler solutions for just left-anchored patterns. More about pattern matching and performance:

    • Pattern matching with LIKE, SIMILAR TO or regular expressions

    pg_trgm also provides useful operators for "similarity" (%) and "distance" (<->).

    Trigram indexes also support simple regular expressions with ~ et al. and case insensitive pattern matching with ILIKE:

    • PostgreSQL accent + case insensitive search
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In Microsoft SQL Server 10, how do I set constraint, that column in table
In Microsoft SQL Server : I've added an insert trigger my table ACCOUNTS that
Consider Microsoft SQL Server 2008 I need to create a table which can be
Using Microsoft SQL Server. Running a stored procedure that returns 'No column name' as
Microsoft SQL Server has a nice feature, which allows a database to be automatically
Microsoft SQL Server seems to check column name validity, but not table name validity
We have a Microsoft SQL Server 2005 database that needs to be converted back
Using Microsoft SQL Server 2005, is there any way to see when a table
In Microsoft SQL Server 2008, when executing .query('{xpath}/text()') on an XML stream column value,
Using Microsoft SQL server 2008 I have a query that is in need of

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.