sql >> Databáze >  >> RDS >> PostgreSQL

Podporuje PostgreSQL kolace bez přízvuku?

Použijte modul unaccent za to – což je úplně jiné než to, na co odkazujete.

unaccent je slovník pro vyhledávání v textu, který odstraňuje diakritická znaménka z lexémů.

Nainstalujte jednou na databázi pomocí:

CREATE EXTENSION unaccent;

Pokud se zobrazí chyba jako:

ERROR: could not open extension control file
"/usr/share/postgresql/<version>/extension/unaccent.control": No such file or directory

Nainstalujte balíček contrib na svůj databázový server podle pokynů v této související odpovědi:

  • Chyba při vytváření nezvýrazněného rozšíření na PostgreSQL

Mimo jiné poskytuje funkci unaccent() můžete použít ve svém příkladu (kde ILIKE zdá se, že to není potřeba).

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

Index

Chcete-li pro tento druh dotazu použít index, vytvořte pro výraz index. Nicméně , Postgres přijímá pouze IMMUTABLE funkce pro indexy. Pokud funkce může vrátit jiný výsledek pro stejný vstup, index se může tiše zlomit.

unaccent() pouze STABLE není IMMUTABLE

Bohužel unaccent() je pouze STABLE , nikoli IMMUTABLE . Podle tohoto vlákna na pgsql-bugs je to kvůli třem důvody:

  1. Záleží na chování slovníku.
  2. K tomuto slovníku není žádné pevné připojení.
  3. Záleží tedy také na aktuální search_path , který se může snadno změnit.

Některé výukové programy na webu doporučují pouze změnit volatilitu funkce na IMMUTABLE . Tato metoda hrubé síly se může za určitých podmínek zlomit.

Jiní navrhují jednoduchý IMMUTABLE funkce wrapper (jako jsem to dělal v minulosti).

Probíhá debata, zda udělat variantu se dvěma parametry IMMUTABLE který použitý slovník výslovně deklaruje. Přečtěte si zde nebo zde.

Další alternativou by byl tento modul s IMMUTABLE unaccent() funkce Musicbrainz, poskytovaná na Github. Sám jsem to netestoval. Myslím, že jsem přišel na lepší nápad :

Zatím nejlepší

Tento přístup je efektivnější než ostatní řešení a bezpečnější .
Vytvořte IMMUTABLE Funkce SQL wrapper spouštějící dvouparametrový formulář s pevně zapojenou funkcí a slovníkem kvalifikovanou pro schéma.

Protože vnoření neměnné funkce by znemožnilo vkládání funkce, založte ji na kopii C-funkce (falešné) deklarované IMMUTABLE také. Jeho pouze Účelem je použití v obalu funkce SQL. Není určeno k použití samostatně.

Je zapotřebí sofistikovanosti, protože neexistuje způsob, jak pevně zapojit slovník do deklarace funkce C. (Vyžadovalo by hacknutí samotného kódu C.) Funkce SQL wrapper to dělá a umožňuje vkládání funkcí a indexy výrazů.

CREATE OR REPLACE FUNCTION public.immutable_unaccent(regdictionary, text)
  RETURNS text LANGUAGE c IMMUTABLE PARALLEL SAFE STRICT AS
'$libdir/unaccent', 'unaccent_dict';

CREATE OR REPLACE FUNCTION public.f_unaccent(text)
  RETURNS text LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS
$func$
SELECT public.immutable_unaccent(regdictionary 'public.unaccent', $1)
$func$;

Pusťte PARALLEL SAFE z obou funkcí pro Postgres 9.5 nebo starší.

public je schéma, do kterého jste rozšíření nainstalovali (public je výchozí).

Explicitní deklarace typu (regdictionary ) chrání před hypotetickými útoky přetíženými variantami funkce ze strany uživatelů se zlými úmysly.

Dříve jsem obhajoval funkci wrapper založenou na STABLE funkce unaccent() dodáváno s unaccent modulem. Tato deaktivovaná funkce vkládání. Tato verze se spustí desetkrát rychleji než jednoduchá funkce wrapper, kterou jsem zde měl dříve.
A to už bylo dvakrát rychlejší než první verze, která přidala SET search_path = public, pg_temp k funkci - dokud jsem nezjistil, že slovník lze také kvalifikovat podle schématu. Přesto (Postgres 12) není z dokumentace příliš zřejmé.

Pokud chybí vám potřebná oprávnění k vytváření funkcí C, jste zpět u druhé nejlepší implementace:IMMUTABLE funkce wrapper kolem STABLE unaccent() funkce poskytovaná modulem:

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

Nakonec index výrazů aby byly dotazy rychlé :

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

Nezapomeňte znovu vytvořit indexy zahrnout tuto funkci po jakékoli změně funkce nebo slovníku, jako je upgrade hlavní verze na místě, který by nevytvářel indexy. Všechny poslední hlavní verze obsahovaly aktualizace pro unaccent modul.

Přizpůsobte dotazy tak, aby odpovídaly indexu (takže je použije plánovač dotazů):

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

Nepotřebujete funkci ve správném výrazu. Zde můžete také zadat řetězce bez akcentu jako 'Joao' přímo.

Rychlejší funkce se nepřevádí na mnohem rychlejší dotazy pomocí indexu výrazů . To funguje na předem vypočítaných hodnotách a je již velmi rychlé. Ale údržba indexu a dotazy nevyužívají výhody indexu.

Zabezpečení klientských programů bylo posíleno s Postgres 10.3 / 9.6.8 atd. potřebujete k určení funkce a názvu slovníku podle schématu, jak je ukázáno při použití v jakýchkoli indexech. Viz:

  • „slovník textového vyhledávání „nepřízvuk“ neexistuje' záznamy v protokolu postgres, pravděpodobně během automatické analýzy

Ligy

V Postgres 9.5 nebo starší ligatury jako 'Œ' nebo 'ß' je třeba rozbalit ručně (pokud to potřebujete), protože unaccent() vždy nahradí single písmeno:

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

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

Tato aktualizace se vám v Postgres 9.6 bude líbit :

Rozšířit contrib/unaccent standardní unaccent.rules pro zpracování všech diakritik známých Unicode a správné rozbalení ligatur (ThomasMunro, Léonard Benedetti)

Odvážný důraz můj. Nyní dostáváme:

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

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

Shoda vzorů

Za ILIKE nebo ILIKE s libovolnými vzory, zkombinujte to s modulem pg_trgm v PostgreSQL 9.1 nebo novějším. Vytvořte trigramový GIN (obvykle preferovaný) nebo výrazový index GIST. Příklad pro GIN:

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

Lze použít pro dotazy jako:

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

Udržování indexů GIN a GIST je dražší než prostý btree:

  • Rozdíl mezi indexem GiST a GIN

Pro pouze vlevo ukotvené vzory existují jednodušší řešení. Více o porovnávání vzorů a výkonu:

  • Shoda vzoru s LIKE, SIMILAR TO nebo regulárními výrazy v PostgreSQL

pg_trgm také poskytuje užitečné operátory pro "podobnost" (% ) a "vzdálenost" (<-> ).

Trigram indexy také podporují jednoduché regulární výrazy s ~ a kol. a nerozlišují se malá a velká písmena shoda vzoru s ILIKE :

  • Přízvuk v PostgreSQL + vyhledávání bez rozlišení velkých a malých písmen


  1. Může PostgreSQL provést spojení mezi dvěma uloženými procedurami SQL Serveru?

  2. MySQL nemůže přidat omezení cizího klíče

  3. Výpočet rozdílu mezi dvěma časovými razítky v Oracle v milisekundách

  4. Typy polí a použití v databázích Accessu 2019