UNACCENT when checking for UNIQUE contraint violations in PostgreSQL

557 Views Asked by At

We have a UNIQUE constraint on a table to prevent our city_name and state_id combinations from being duplicated. The problem we have found is that accents circumvent this.

Example: "Montréal" "Quebec" and "Montreal" "Quebec"

We need a way to have the unique constraint run UNACCENT() and preferably wrap it in LOWER() as well for good measure. Is this possible?

2

There are 2 best solutions below

4
Cody Caughlan On

You can create unique indexes on expressions, see the Postgres manual:

https://www.postgresql.org/docs/9.3/indexes-expressional.html

So in your case it could be something like

CREATE UNIQUE INDEX idx_foo ON my_table ( UNACCENT(LOWER(city_name)), state_id )

0
Laurenz Albe On

You can create an immutable version of unaccent:

CREATE FUNCTION noaccent(text) RETURNS text
   LANGUAGE sql IMMUTABLE STRICT AS
'SELECT unaccent(lower($1))';

and use that in a unique index on the column.

An alternative is to use a BEGORE INSERT OR UPDATE trigger that fills a new column with the unaccented value and put a unique constraint on that column.