PostgreSQL SELECT如果字符串包含


105

所以我的Postgresql中有一个:

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

为了简化我的问题,当字符串“ aaaaaaaa”包含“ tag_name”时,我想从TAG_TABLE中选择“ id”。因此,理想情况下,它应该仅返回“ 1”,这是标记名称“ aaa”的ID

这是我到目前为止所做的:

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

但是显然,这是行不通的,因为postgres认为'%tag_name%'意味着包含子字符串'tag_name'而不是该列下实际数据值的模式。

如何将tag_name传递给模式?

Answers:


131

您应该在引号之外使用“ tag_name”;然后将其解释为记录的字段。使用“ ||”连接 具有文字百分号:

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

5
当tag_name是什么时,会发生"; drop table TAG_TABLE; --"什么?
Denis de Bernardy 2014年

24
@Denis:什么都没发生。您没有得到任何行,因为该WHERE子句的计算结果为FALSE。该语句不是动态的,仅连接了值,没有机会进行SQL注入。
Erwin Brandstetter

1
不应该将aaaa和tag_name的顺序颠倒吗?我的意思是,您应该在列之后放置一列名称
user151496 2015年

@ user151496否,因为该模式必须位于LIKE关键字的右侧。
jpmc26 2016年

4
当心在LIKE模式中使用变量时,如果这些变量包含下划线(_)或百分比字符(%),可能会产生意想不到的后果。例如,可能需要使用以下功能来转义这些字符CREATE OR REPLACE FUNCTION quote_for_like(text) RETURNS text LANGUAGE SQL IMMUTABLE AS $$ SELECT regexp_replace($1, '([\%_])', '\\\1', 'g'); $$;:(来自Freenode上#postgresql IRC通道的用户MatheusOl)。
Martin von Wittich

46

我个人更喜欢〜运算符的简单语法。

SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' ~ tag_name;

值得阅读Postgres中的LIKE和〜之间的差异以了解差异。`


2
这仅在tag_name适当的REGEX时有效。风险很大。
雅各布·费迪恰克

@JakubFedyczak可以匹配您可以使用的文字tag_name,***=这在postgresql.org/docs/current/static/functions-matching.html中已提到。但是我发现与strpos/ position解决方案相比要慢得多。
phunehehe

27

以搜索一个子一个适当的方法是使用position函数代替like表达,这需要逸出%_和转义字符(\默认情况下):

SELECT id FROM TAG_TABLE WHERE position(tag_name in 'aaaaaaaaaaa')>0;

这是正确的方法。没有人应该使用hacky regex方法。
khol

LIKEILIKE可以使用gin索引。position不能。
Eugene Pakhomov

14

除了用该溶液'aaaaaaaa' LIKE '%' || tag_name || '%'position(参数的相反的顺序)和strpos

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

除了更有效的方法(LIKE看起来效率较低,但是索引可能会改变事情)之外,LIKE还有一个非常小的问题:tag_name当然不应包含%(尤其是_(单字符通配符)),以免出现误报。


2
我必须用位置替换strpos,因为strpos总是为我返回0
jcf

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

tag_name 应该用引号引起来,否则会报错,因为tag_name不存在


2
这与公认的答案完全相反。您正在串联为字符串,但它必须是一列...
Suraj Rao
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.