PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Funzione di escape per espressioni regolari o modelli LIKE

Per rispondere alla domanda in alto:

Funzione di escape dell'espressione regolare

Iniziamo con un elenco completo di caratteri con un significato speciale in espressione regolare modelli:

!$()*+.:<=>?[\]^{|}-

Racchiusi tra parentesi, la maggior parte di essi perde il suo significato speciale, con alcune eccezioni:

  • - deve essere il primo o l'ultimo o indica un intervallo di caratteri.
  • ] e \ devono essere evitati con \ (anche nella sostituzione).

Dopo aver aggiunto le parentesi di acquisizione per il riferimento indietro di seguito, otteniamo questo modello di espressione regolare:

([!$()*+.:<=>?[\\\]^{|}-])

Usandolo, questa funzione esegue l'escape di tutti i caratteri speciali con una barra rovesciata (\ ) - eliminando così il significato speciale:

CREATE OR REPLACE FUNCTION f_regexp_escape(text)
  RETURNS text
  LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS
$func$
SELECT regexp_replace($1, '([!$()*+.:<=>?[\\\]^{|}-])', '\\\1', 'g')
$func$;

Aggiungi PARALLEL SAFE (perché è ) in Postgres 10 o versioni successive per consentire il parallelismo per le query che lo utilizzano.

Dimostrazione

SELECT f_regexp_escape('test(1) > Foo*');

Resi:

test\(1\) \> Foo\*

E mentre:

SELECT 'test(1) > Foo*' ~ 'test(1) > Foo*';

restituisce FALSE , che potrebbe sorprendere gli utenti ingenui,

SELECT 'test(1) > Foo*' ~ f_regexp_escape('test(1) > Foo*');

Restituisce TRUE come dovrebbe ora.

LIKE funzione di escape

Per completezza, il ciondolo per LIKE pattern, dove solo tre caratteri sono speciali:

\%_

Il manuale:

Il carattere di escape predefinito è la barra rovesciata, ma è possibile selezionarne uno diverso utilizzando ESCAPE clausola.

Questa funzione assume l'impostazione predefinita:

CREATE OR REPLACE FUNCTION f_like_escape(text)
  RETURNS text
  LANGUAGE sql IMMUTABLE STRICT PARALLEL SAFE AS
$func$
SELECT replace(replace(replace($1
         , '\', '\\')  -- must come 1st
         , '%', '\%')
         , '_', '\_');
$func$;

Potremmo usare il più elegante regexp_replace() anche qui, ma per i pochi caratteri, una cascata di replace() funzioni è più veloce.

Di nuovo, PARALLEL SAFE in Postgres 10 o successivo.

Dimostrazione

SELECT f_like_escape('20% \ 50% low_prices');

Resi:

20\% \\ 50\% low\_prices