1

Short version: I need a function to escape strings for use in LIKE expressions, so fr_e%d becomes fr\_e\%d.


I'm looking for escape the result of a query without the need to use replace. Because in this result I have path with this char _ inside. And because I use this result in a LIKE statement, it make the "_" a joker like start *.

I have to use LIKE because I'm doing some stuff concatenation in this same statement who need the fact that I use LIKE.

I tried ~ to replace LIKE but I will have the same problem with the char '.' because ~ is to use regex just skip this solution too.

0

2 Answers 2

4
create function quote_like(text) returns text language sql immutable strict as
  $quote_like$
    select regexp_replace($1, $$[_%\\]$$, $$\\\&$$, 'g');
  $quote_like$;

This function prepends all occurrences of _, % and \ in provided string with \. You can use it for example like this:

select * from tablename
  where tablecolumn like
    '%'
    ||
    (select quote_like(substring) from substrings where substring_id=123)
    ||
    '%';
Sign up to request clarification or add additional context in comments.

3 Comments

A single pass with regexp_replace() - even a clean, simple one like in the example - is regularly more expensive than three instances of replace().
@ErwinBrandstetter: you're right — replace(replace(replace(... is somewhat faster than single regexp_replace, but not by much — 15-20% in my tests.
Thanks all for your solutions.
2

Update

Triggered by @Tometzky's claim:

Using regexp_replace is better than simply replace (...)

I have to disagree. Regular expression functions are powerful but comparatively slow.
Therefore, event 3x replace() is faster than a single, simple regexp_replace() - at least in my tests:

CREATE OR REPLACE FUNCTION quote_like2(text)
  RETURNS text LANGUAGE SQL IMMUTABLE STRICT AS
$func$
SELECT replace(replace(replace(
         $1
        ,'\', '\\') -- must come first
        ,'_', '\_')
        ,'%', '\%');
$func$;

Note that I use plain single quotes instead of dollar quoting. This requires standard_conforming_strings = on, which is the default since PostgreSQL 9.1.

Try both functions with your data:

EXPLAIN ANALYZE SELECT quote_like1(col) from tbl;

Original answer

Contrary to you question title, you would normally use replace() or a similar string function to prepare your pattern. Consider this demo:

SELECT 'abcde' LIKE ('abc_' || '%')  -- TRUE
      ,'abc_e' LIKE ('abc_' || '%')  -- TRUE
      ,'abcde' LIKE (replace('abc_', '_', '\_')  || '%')   -- FALSE
      ,'abc_e' LIKE (replace('abc_', '_', '\_')  || '%');  -- TRUE

1 Comment

You're right too, especially about what solution is faster. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.