W Microsoft SQL Server można określić sortowanie „niewrażliwe na akcenty” (dla bazy danych, tabeli lub kolumny), co oznacza, że jest możliwe dla zapytania takiego jak
SELECT * FROM users WHERE name LIKE 'João'
aby znaleźć wiersz z Joao
nazwą.
Wiem, że w PostgreSQL można usunąć akcenty z ciągów znaków za pomocą funkcji dodawania unaccent_string, ale zastanawiam się, czy PostgreSQL obsługuje te sortowania „niewrażliwe na akcenty”, aby SELECT
powyższe działało.
sql
postgresql
localization
indexing
pattern-matching
Daniel Serodio
źródło
źródło
Odpowiedzi:
Użyj do tego modułu bez akcentu - który jest zupełnie inny niż to, do którego tworzysz link.
Zainstaluj raz na bazę danych za pomocą:
Jeśli pojawi się błąd, taki jak:
Zainstaluj pakiet Contrib na serwerze bazy danych, zgodnie z instrukcją w tej powiązanej odpowiedzi:
Między innymi zapewnia funkcję,
unaccent()
której możesz użyć na swoim przykładzie (gdzieLIKE
wydaje się, że nie jest potrzebna).Indeks
Aby użyć indeksu dla tego rodzaju zapytania, utwórz indeks dla wyrażenia . Jednak Postgres akceptuje tylko
IMMUTABLE
funkcje dla indeksów. Jeśli funkcja może zwrócić inny wynik dla tego samego wejścia, indeks może po cichu przerwać.unaccent()
tylkoSTABLE
nieIMMUTABLE
Niestety
unaccent()
tylkoSTABLE
nieIMMUTABLE
. Zgodnie z tym wątkiem dotyczącym błędów pgsql , wynika to z trzech powodów:search_path
, który może się łatwo zmieniać.Niektóre samouczki w sieci WWW zalecają zmianę zmienności funkcji na
IMMUTABLE
. Ta metoda brutalnej siły może się zepsuć w pewnych warunkach.Inni sugerują prostą
IMMUTABLE
funkcję opakowującą (tak jak ja robiłem to w przeszłości).Trwa debata, czy utworzyć wariant z dwoma parametrami,
IMMUTABLE
który jawnie deklaruje używany słownik. Przeczytaj tutaj lub tutaj .Inną alternatywą byłoby moduł z niezmiennymi
unaccent()
funkcji przez Musicbrainz , umieszczonych na Github. Sam tego nie testowałem. Myślę, że wpadłem na lepszy pomysł :Na razie najlepsze
Takie podejście jest bardziej wydajne niż inne rozwiązania i bezpieczniejsze .
Utwórz funkcję
IMMUTABLE
opakowującą SQL wykonującą formularz dwuparametrowy z okablowaną funkcją kwalifikowaną schematu i słownikiem.Od gniazdowania non-niezmienny funkcję spowodowałoby wyłączenie funkcji inline, baza go na kopii C-funkcji (fałszywej) ogłosił
IMMUTABLE
również. Jego jedynym celem jest użycie w opakowaniu funkcji SQL. Nie jest przeznaczony do samodzielnego użytku.Wymagane jest wyrafinowanie, ponieważ nie ma sposobu na trwałe połączenie słownika w deklaracji funkcji C. (Wymagałoby to zhakowania samego kodu C.) Funkcja opakowująca SQL robi to i umożliwia zarówno wstawianie funkcji, jak i indeksy wyrażeń.
Usuń
PARALLEL SAFE
z obu funkcji dla Postgres 9.5 lub starszych.public
jest schematem, w którym zainstalowałeś rozszerzenie (public
jest to ustawienie domyślne).Jawna deklaracja typu (
regdictionary
) chroni przed hipotetycznymi atakami z przeciążonymi wariantami funkcji ze strony złośliwych użytkowników.Wcześniej opowiadałem się za funkcją opakowującą opartą na
STABLE
funkcjiunaccent()
dostarczanej z modułem unaccent. Ta wyłączona funkcja inlining . Ta wersja wykonuje dziesięć razy szybciej niż prosta funkcja opakowująca, którą miałem tutaj wcześniej.Było to już dwa razy szybsze niż pierwsza wersja, która została dodana
SET search_path = public, pg_temp
do funkcji - dopóki nie odkryłem, że słownik również może być kwalifikowany według schematu. Jednak (Postgres 12) nie jest zbyt oczywiste z dokumentacji.Jeśli nie masz uprawnień niezbędnych do tworzenia funkcji w C, wracasz do drugiej najlepszej implementacji:
IMMUTABLE
opakowania funkcji wokółSTABLE
unaccent()
funkcji udostępnianej przez moduł:Na koniec indeks wyrażeń do szybkiego wykonywania zapytań :
Pamiętaj o ponownym utworzeniu indeksów obejmujących tę funkcję po każdej zmianie funkcji lub słownika, na przykład po uaktualnieniu głównej wersji w miejscu, które nie spowoduje odtworzenia indeksów. Wszystkie ostatnie główne wydania zawierały aktualizacje
unaccent
modułu.Dostosuj zapytania do indeksu (aby planista zapytań go użył):
Nie potrzebujesz funkcji w odpowiednim wyrażeniu. Można tam również dostarczyć sznurki bez akcentu, jak
'Joao'
bezpośrednio.Szybsza funkcja nie przekłada się na znacznie szybsze zapytania korzystające z indeksu wyrażenia . To działa na wstępnie obliczonych wartościach i jest już bardzo szybkie. Ale utrzymanie indeksu i zapytania nie korzystają z indeksu.
Zabezpieczeń dla programów klienckich zostały dokręcone PostgreSQL 10,3 / 9.6.8 itp Państwo potrzebują do schematu zakwalifikować funkcję i nazwę słownika, jak wykazano w przypadku stosowania w dowolnych pozycjach. Widzieć:
Ligatury
W Postgres 9.5 lub starszych ligaturach, takich jak `` Œ '' lub `` ß '', należy rozszerzyć ręcznie (jeśli jest to potrzebne), ponieważ
unaccent()
zawsze zastępuje jedną literę:Spodoba ci się ta aktualizacja, która zniknęła w Postgres 9.6 :
Odważne podkreślenie moje. Teraz otrzymujemy:
Dopasowanie wzorców
Dla
LIKE
lubILIKE
z dowolnymi wzorcami, połącz to z modułempg_trgm
w PostgreSQL 9.1 lub nowszym. Utwórz trygram GIN (zazwyczaj preferowany) lub indeks wyrażenia GIST. Przykład dla WZ:Może być używany do zapytań takich jak:
Indeksy GIN i GIST są droższe w utrzymaniu niż zwykłe btree:
Istnieją prostsze rozwiązania dla wzorów zakotwiczonych w lewo. Więcej o dopasowywaniu wzorców i wydajności:
pg_trgm
zawiera również przydatne operatory dla „podobieństwa” (%
) i „odległości” (<->
) .Indeksy Trigram obsługują również proste wyrażenia regularne z
~
et al. i dopasowywanie wzorca bez rozróżniania wielkości liter zILIKE
:źródło
unaccent(name)
?utf8_general_ci
odpowiedzią na tego rodzaju problemy?Nie, PostgreSQL nie obsługuje sortowania w tym sensie
PostgreSQL nie obsługuje tego typu sortowania (bez uwzględniania akcentu lub nie), ponieważ żadne porównanie nie może zwrócić równości, chyba że rzeczy są binarnie równe. Dzieje się tak, ponieważ wewnętrznie wprowadziłoby to wiele złożoności dla rzeczy takich jak indeks skrótu. Z tego powodu zestawienia w najściślejszym znaczeniu mają wpływ tylko na porządek, a nie na równość.
Obejścia
Słownik wyszukiwania pełnotekstowego, który usuwa leksemy.
W przypadku FTS możesz zdefiniować własny słownik za pomocą
unaccent
,Które możesz następnie zindeksować za pomocą indeksu funkcjonalnego,
Możesz teraz zapytać go w bardzo prosty sposób
Zobacz też
Sam w sobie nieakcentowany.
unaccent
Moduł może być również stosowany samodzielnie bez FTS-integracji, w tym wyjazd odpowiedź Erwinaźródło
Jestem prawie pewien, że PostgreSQL polega na podstawowym systemie operacyjnym do sortowania. To ma wspierać tworzenie nowych sortowania i dostosowywania ustawień sortowania . Nie jestem jednak pewien, ile może to być pracy dla Ciebie. (Może być całkiem sporo.)
źródło