В Microsoft SQL Server можно указать параметры сортировки «без учета акцента» (для базы данных, таблицы или столбца), что означает, что это возможно для запроса типа
SELECT * FROM users WHERE name LIKE 'João'
найти строку с Joao
именем.
Я знаю , что можно раздеться акцентами из строк в PostgreSQL с использованием unaccent_string функции вна, но мне интересно , если PostgreSQL поддерживает эти «акцент» нечувствительные поэтому сопоставления SELECT
выше будет работать.
sql
postgresql
localization
indexing
pattern-matching
Даниэль Серодио
источник
источник
Ответы:
Используйте для этого модуль unaccent , который полностью отличается от того, на что вы ссылаетесь.
Установите один раз для каждой базы данных с помощью:
Если вы получите сообщение об ошибке:
Установите пакет contrib на свой сервер базы данных, как указано в соответствующем ответе:
Среди прочего, он предоставляет функцию, которую
unaccent()
вы можете использовать в своем примере (там, где этоLIKE
кажется ненужным).Индекс
Чтобы использовать индекс для такого типа запроса, создайте индекс для выражения . Однако Postgres принимает
IMMUTABLE
функции только для индексов. Если функция может вернуть другой результат для одного и того же ввода, индекс может молча прерваться.unaccent()
толькоSTABLE
неIMMUTABLE
К сожалению,
unaccent()
толькоSTABLE
нетIMMUTABLE
. Согласно этой теме на pgsql-bugs , это происходит по трем причинам:search_path
, который может легко измениться.Некоторые обучающие программы в Интернете инструктируют просто изменить волатильность функции на
IMMUTABLE
. Этот метод грубой силы может сломаться при определенных условиях.Другие предлагают простую
IMMUTABLE
функцию-оболочку (как я сам делал в прошлом).Продолжаются дискуссии о том, следует ли делать вариант с двумя параметрами,
IMMUTABLE
который явно объявляет используемый словарь. Читайте здесь или здесь .Другая альтернатива была бы этот модуль с непреложной
unaccent()
функцией по MusicBrainz , представленной на Github. Сам не тестировал. Думаю, я придумал лучшую идею :Лучшее на данный момент
Этот подход более эффективен, чем другие решения, и безопаснее .
Создайте функцию-
IMMUTABLE
оболочку SQL, выполняющую двухпараметрическую форму с зашитой функцией и словарем, квалифицированной схемой.Поскольку вложение неизменяемой функции отключит встраивание функции, основывайте его на копии объявленной C-функции (поддельной)
IMMUTABLE
. Его единственное назначение - использовать в оболочке функции SQL. Не предназначен для использования отдельно.Изощренность необходима, поскольку нет возможности жестко привязать словарь к объявлению функции C. (Потребуется взломать сам код C.) Функция-оболочка SQL делает это и позволяет как встраивание функций, так и индексы выражений.
Откажитесь
PARALLEL SAFE
от обеих функций для Postgres 9.5 или старше.public
Схема, в которую вы установили расширение (public
по умолчанию).Явное объявление типа (
regdictionary
) защищает от гипотетических атак злонамеренных пользователей с перегруженными вариантами функции.Ранее я выступал за функцию-оболочку, основанную на
STABLE
функции,unaccent()
поставляемой с модулем unaccent. Эта отключенная функция встраивается . Эта версия выполняется в десять раз быстрее, чем простая функция-оболочка, которую я использовал здесь ранее.И это было уже в два раза быстрее, чем в первой версии, добавленной
SET search_path = public, pg_temp
к функции - пока я не обнаружил, что словарь также может быть квалифицирован по схеме. Тем не менее (Postgres 12) не слишком очевиден из документации.Если у вас нет необходимых привилегий для создания функций C, вы вернетесь ко второй лучшей реализации:
IMMUTABLE
обертка функции вокругSTABLE
unaccent()
функции, предоставляемой модулем:Наконец, индекс выражения для быстрого выполнения запросов :
Не забудьте воссоздать индексы, включающие эту функцию, после любого изменения функции или словаря, например, при обновлении основного выпуска на месте, при котором индексы воссоздавать не будут. Все последние основные выпуски содержали обновления
unaccent
модуля.Адаптируйте запросы к индексу (чтобы планировщик запросов использовал его):
Вам не нужна функция в правильном выражении. Там вы также можете указать строки без ударения, например,
'Joao'
напрямую.Более быстрая функция не преобразуется в гораздо более быстрые запросы с использованием индекса выражения . Это работает с предварительно вычисленными значениями и уже работает очень быстро. Но обслуживание индекса и запросы, не использующие преимущества индекса.
Безопасность клиентских программ была усилена с помощью Postgres 10.3 / 9.6.8 и т. Д. Вам необходимо указать функцию и имя словаря с указанием схемы, как показано при использовании в любых индексах. Видеть:
Лигатуры
В Postgres 9.5 или более ранних лигатуры, такие как 'Œ' или 'ß', должны быть расширены вручную (если вам это нужно), поскольку
unaccent()
всегда заменяет одну букву:Вам понравится это обновление до Unaccent в Postgres 9.6 :
Смелый акцент мой. Теперь получаем:
Сопоставление с образцом
Для произвольных шаблонов
LIKE
илиILIKE
с ними объедините это с модулемpg_trgm
в PostgreSQL 9.1 или новее. Создайте триграмму GIN (обычно предпочтительнее) или индекс выражения GIST. Пример для GIN:Может использоваться для таких запросов:
Индексы GIN и GIST обходятся дороже, чем обычные btree:
Есть более простые решения только для шаблонов с левым якорем. Подробнее о сопоставлении с образцом и производительности:
pg_trgm
также предоставляет полезные операторы для «подобия» (%
) и «расстояния» (<->
). .Индексы триграммы также поддерживают простые регулярные выражения с помощью
~
et al. и чувствителен к регистру сопоставление с образцом сILIKE
:источник
unaccent(name)
?utf8_general_ci
является ответом на подобные проблемы?Нет, PostgreSQL не поддерживает сопоставления в этом смысле
PostgreSQL не поддерживает такие сопоставления (без учета акцента или без него), потому что никакое сравнение не может вернуть равное, если только вещи не являются двоичными. Это связано с тем, что внутренне это внесло бы много сложностей для таких вещей, как хеш-индекс. По этой причине сопоставления в их самом строгом смысле влияют только на порядок, а не на равенство.
Обходные пути
Словарь с полнотекстовым поиском без акцентов.
Для FTS вы можете определить свой собственный словарь, используя
unaccent
,Который затем можно проиндексировать с помощью функционального индекса,
Теперь вы можете запросить его очень просто
Смотрите также
Сам по себе без акцента.
unaccent
Модуль также может быть использован сам по себе , без FTS-интеграции, для этого заканчивал ответ Эрвиныисточник
Я почти уверен, что PostgreSQL полагается на базовую операционную систему для сортировки. Это действительно поддерживает создание новых параметров сортировки и настройки сортировки . Однако я не уверен, сколько работы это может быть для вас. (Может быть довольно много.)
источник