【问题标题】:Postgresql SELECT if string containsPostgresql SELECT 如果字符串包含
【发布时间】:2014-06-12 19:27:07
【问题描述】:

所以我的 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 传递给模式??

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

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

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

    【讨论】:

    • tag_name 为 "; drop table TAG_TABLE; --" 时会发生什么?
    • @Denis:什么也没发生。你没有得到任何行,因为WHERE 子句的计算结果为FALSE。该语句不是动态的,仅连接值,没有 SQL 注入的机会。
    • 不应该是aaaa和tag_name的顺序颠倒了?我的意思是你应该在 where 后面加上一个列名
    • @user151496 否,因为模式必须位于 LIKE 关键字的右侧。
    • 请注意,当这些变量包含下划线 (_) 或百分号 (%) 时,在 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)。
    【解决方案2】:

    搜索子字符串的正确方法是使用position 函数而不是like 表达式,这需要转义%_ 和转义字符(默认为\):

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

    【讨论】:

    • 这是正确的做法。没有人应该使用老套的正则表达式方法。
    • LIKEILIKE 可以使用 gin 索引。 position 不能。
    • @Grigory 你的position 一定有错字。
    【解决方案3】:

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

    SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' ~ tag_name;
    

    值得通过Difference between LIKE and ~ in Postgres 阅读以了解差异。 `

    【讨论】:

    【解决方案4】:

    除了'aaaaaaaa' LIKE '%' || tag_name || '%'的解决方案还有 是position(args 的倒序)和strpos

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

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

    【讨论】:

    • 我不得不用位置替换 strpos,因为 strpos 总是为我返回 0
    【解决方案5】:
    SELECT id FROM TAG_TABLE WHERE 'aaaaaaaa' LIKE '%' || "tag_name" || '%';
    

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

    【讨论】:

    • 这与公认的answer 完全相反。您正在连接为字符串,而它需要是一列......
    • 双引号仍然引用一列,所以这将是相同的
    • ⸻列名有空格的情况。
    猜你喜欢
    • 2019-09-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-13
    • 2021-05-30
    相关资源
    最近更新 更多