231

So I have a in my Postgresql:

TAG_TABLE
==========================
id            tag_name       
--------------------------
1             aaa
2             bbb
3             ccc

To simplify my problem, What I want to do is SELECT 'id' from TAG_TABLE when a string "aaaaaaaa" contains the 'tag_name'. So ideally, it should only return "1", which is the ID for tag name 'aaa'

This is what I am doing so far:

SELECT id FROM TAG_TABLE WHERE 'aaaaaaaaaaa' LIKE '%tag_name%'

But obviously, this does not work, since the postgres thinks that '%tag_name%' means a pattern containing the substring 'tag_name' instead of the actual data value under that column.

How do I pass the tag_name to the pattern??

Braiam
  • 1
  • 11
  • 47
  • 78
user2436815
  • 3,455
  • 5
  • 27
  • 40

6 Answers6

267

You should use tag_name outside of quotes; then it's interpreted as a field of the record. Concatenate using '||' with the literal percent signs:

SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || tag_name || '%';

And remember that LIKE is case-sensitive. If you need a case-insensitive comparison, you could do this:

SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || LOWER(tag_name) || '%';
Dominus.Vobiscum
  • 702
  • 1
  • 9
  • 16
Frans van Buul
  • 3,009
  • 1
  • 13
  • 6
  • 12
    what hapoens when tag_name is `"; drop table TAG_TABLE; --"`? – Denis de Bernardy Apr 27 '14 at 10:21
  • 40
    @Denis: Nothing happens. You get no row, because the `WHERE` clause evaluates to `FALSE`. The statement is not dynamic, only values are concatenated, no chance for SQL injection. – Erwin Brandstetter Apr 27 '14 at 10:48
  • 1
    shouldn't be the order of aaaa and tag_name reversed? i mean that you should put a column name after where – user151496 May 11 '15 at 15:10
  • @user151496 No because the pattern has to go on the right side of the `LIKE` keyword. – jpmc26 Jun 21 '16 at 00:10
  • 11
    Beware that using variables in a `LIKE` pattern may have unintended consequences when those variables contain underscores (_) or percent characters (%). It may be necessary to escape these characters, for example with this function: `CREATE OR REPLACE FUNCTION quote_for_like(text) RETURNS text LANGUAGE SQL IMMUTABLE AS $$ SELECT regexp_replace($1, '([\%_])', '\\\1', 'g'); $$;` (from user MatheusOl from the #postgresql IRC channel on Freenode). – Martin von Wittich Sep 13 '16 at 15:11
  • 1
    This didn't work but [this](https://stackoverflow.com/a/30379009/14967240) did. – Mahmood Nov 13 '21 at 07:29
  • 1
    Use `ILIKE` for case insensitive search. – AJP Apr 08 '22 at 12:24
103

A proper way to search for a substring is to use position function instead of like expression, which requires escaping %, _ and an escape character (\ by default):

SELECT id FROM TAG_TABLE WHERE position(tag_name in 'aaaaaaaaaaa')>0;
Tometzky
  • 22,573
  • 5
  • 59
  • 73
81

I personally prefer the simpler syntax of the ~ operator.

SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' ~ tag_name;

Worth reading through Difference between LIKE and ~ in Postgres to understand the difference. `

Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
keithhackbarth
  • 9,317
  • 5
  • 28
  • 33
  • 5
    This works only when `tag_name` is a proper REGEX. Pretty risky. – Jakub Fedyczak Aug 23 '17 at 09:17
  • 1
    @JakubFedyczak to match literal tag_name you can use `***=` which is mentioned in https://www.postgresql.org/docs/current/static/functions-matching.html. However I have found that to be too much slower compared to the `strpos`/`position` solutions. – phunehehe Oct 09 '18 at 16:33
  • Regexes need to be compiled before they can be matched, so matching against a column name like this means it has to compile a new regex for each row considered, which will be very slow. – harmic Jan 27 '23 at 04:34
27

In addition to the solution with 'aaaaaaaa' LIKE '%' || tag_name || '%' there are position (reversed order of args) and strpos.

SELECT id FROM TAG_TABLE WHERE strpos('aaaaaaaa', tag_name) > 0

Besides what is more efficient (LIKE looks less efficient, but an index might change things), there is a very minor issue with LIKE: tag_name of course should not contain % and especially _ (single char wildcard), to give no false positives.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
1

Try This Simple one

Column Name like '%Vesta%'

Newton8989
  • 300
  • 1
  • 4
  • 22
-4
SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || "tag_name" || '%';

tag_name should be in quotation otherwise it will give error as tag_name doest not exist

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103