Поддерживает ли 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-ошибки, это из-за три причины:
- это зависит от поведения словарь.
- нет жесткого проводного соединения с этим словарем.
- поэтому это также зависит от текущего
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
'стандарт sunaccent.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-интеграции, для этого проверьте ответ Эрвина