Поддерживает ли PostgreSQL" нечувствительные к акценту " параметры сортировки?

В Microsoft SQL Server можно указать" нечувствительные к акценту " параметры сортировки (для базы данных, таблицы или столбца), что означает, что это возможно для запроса типа

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

найти строку с Joao имя.

Я знаю, что можно удалить акценты из строк в PostgreSQL, используя unaccent_string функция contrib, но мне интересно, поддерживает ли PostgreSQL эти" нечувствительные к акценту " параметры сортировки, поэтому SELECT выше работа.

3 ответов


использовать модуль unaccent для того , что совершенно отличается от того, с чем вы связываетесь.

unaccent является поиск текста словаря, который удаляет акценты (диакритические знаки) от лексем.

установите один раз в базу данных с:

CREATE EXTENSION unaccent;

если вы получаете ошибку, как:

ошибка: не удалось открыть файл управления расширением "/usr / share / postgresql / 9.х/расширение/unaccent.контроль": Нет такого файла или каталог

установите пакет contrib на сервер базы данных, как указано в этом соответствующем ответе:

среди прочего, он обеспечивает функцию unaccent() вы можете использовать с вашим примером (где LIKE кажется, не необходимый.)

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

индекс

чтобы использовать индекс для такого запроса, создайте индекс по выражению. , и Postgres принимает только IMMUTABLE функции для индексов. Если функция может возвращать другой результат для одного и того же ввода, индекс может молча сломаться.

unaccent() только STABLE не IMMUTABLE

к сожалению, unaccent() только STABLE, а не IMMUTABLE. Согласно этот поток на pgsql-ошибки, это из-за три причины:

  1. это зависит от поведения словарь.
  2. нет жесткого проводного соединения с этим словарем.
  3. поэтому это также зависит от текущего search_path, который может легко измениться.

обучение в интернете проинструктируйте, чтобы просто изменить волатильность функции на IMMUTABLE. Этот метод грубой силы может сломать под ряд условий.

другие предлагаю простой IMMUTABLE функции-оболочки (как и я сам в прошлом).

существует постоянная дискуссия о том, следует ли сделать вариант с двумя параметрами IMMUTABLE который явно объявляет используемый словарь. Читать здесь или здесь.

Другой альтернативой будет этот модуль с неизменяемые unaccent() функция Musicbrainz, предоставлено на Github. Сам не проверял. Я думаю, что я придумал лучшая идея:

теперь

я предлагаю подход, который по крайней мере так же эффективно, как и другие решения, плавающие вокруг, но безопаснее: Создайте функцию-оболочку с двухпараметрической формой и "жесткой" схемой для функции и словаря:

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

public будучи схемой, где вы установили расширение (public по умолчанию).

ранее, я добавил SET search_path = public, pg_temp к функции-пока я не обнаружил, что словарь также может быть квалифицирован схемой,который в настоящее время (стр. 10) не документирован. Эта версия немного короче и примерно в два раза быстрее в моих тестах на pg 9.5 и pg 10.

обновленная версия по-прежнему не позволяет функция inlining потому что функции, объявленные IMMUTABLE может не вызвать не-неизменными функции организма позволяют это. Вряд ли имеет значение для производительности при использовании индекс выражение на :

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

безопасность для клиентских программ была ужесточена с помощью Postgres 10.3/9.6.8 и т. д. Вы нужно к схеме-квалифицируйте функцию и словарь как показано при использовании в любых индексах. См.:

адаптируйте свои запросы в соответствии с индексом (чтобы планировщик запросов мог его использовать):

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

вам не нужна функция в правильном выражении. Вы можете предоставить безличные строки, такие как 'Joao' напрямую.

лигатур

В Postgres 9.5 и старше лигатуры, такие как " Œ " или "ß", должны быть расширены вручную (Если вам это нужно), так как unaccent() всегда заменяет один письмо:

SELECT unaccent('Œ Æ œ æ ß');

unaccent
----------
E A e a S

вы будете любить это обновление до unaccent в Postgres 9.6:

расширения contrib/unaccent'стандарт s unaccent.rules файл для обработки всех диакритика, известная в Unicode, и правильно развернуть лигатуры (Томас Munro, Léonard Benedetti)

жирным выделено мной. Теперь мы получаем:

SELECT unaccent('Œ Æ œ æ ß');

unaccent
----------
OE AE oe ae ss

шаблон соответствие

на LIKE или ILIKE с произвольными шаблонами объедините это с модулем pg_trgm в PostgreSQL 9.1 или более поздней версии. Создайте триграмму GIN (обычно предпочтительно) или индекс выражения GIST. Пример для Джина:

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

может использоваться для таких запросов, как:

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

индексы джина и GIST дороже поддерживать чем равнина btree:

существуют более простые решения для только левых моделей. Подробнее о сопоставлении шаблонов и производительности:

pg_trgm также предоставляет полезную операторы для "подобия" (%) и "расстояние" (<->).

индексы триграмм также поддерживают простые регулярные выражения с ~ et al. и регистр поиск по шаблону с ILIKE:


Я уверен, что PostgreSQL полагается на базовую операционную систему для сортировки. Это тут поддержка создание новых параметров сортировки и настройка параметров сортировки. Хотя я не уверен, сколько это может быть для тебя работы. (Может быть довольно много.)


нет, PostgreSQL не поддерживает параметры сортировки в этом смысле

PostgreSQL не поддерживает такие параметры сортировки (нечувствительные к акценту или нет), потому что никакое сравнение не может вернуть равенство, если вещи не являются двоичными. Это связано с тем, что внутри он будет вводить много сложностей для таких вещей, как хэш-индекс. По этой причине сортировки в их самом строгом смысле влияет только на заказ и не равенство.

решения

полнотекстовый поиск по словарю, что Unaccents лексем.

для FTS, вы можете определить свой собственный словарь, используя unaccent,

CREATE EXTENSION unaccent;

CREATE TEXT SEARCH CONFIGURATION mydict ( COPY = simple );
ALTER TEXT SEARCH CONFIGURATION mydict
  ALTER MAPPING FOR hword, hword_part, word
  WITH unaccent, simple;

который вы можете затем индексировать с функциональным индексом,

-- Just some sample data...
CREATE TABLE myTable ( myCol )
  AS VALUES ('fóó bar baz'),('qux quz');

-- No index required, but feel free to create one
CREATE INDEX ON myTable
  USING GIST (to_tsvector('mydict', myCol));

теперь вы можете запросить его очень просто

SELECT *
FROM myTable
WHERE to_tsvector('mydict', myCol) @@ 'foo & bar'

    mycol    
-------------
 fóó bar baz
(1 row)

см. также

Unaccent сам по себе.

на unaccent модуль также может использоваться сам по себе без FTS-интеграции, для этого проверьте ответ Эрвина