反斜杠在LIKE子句中的工作不正确

4

我需要使用LIKE和反斜杠来搜索一些名称。问题是Postgres在LIKE子句中将反斜杠理解为转义字符。我尝试打开standard_conforming_strings但是它没有帮助。

SELECT h.software_id
    ,h.software_name
FROM software h
WHERE software_name LIKE '%\%';

这个查询没有显示任何内容,但我有一个软件名称'\'。

我听说过有人提到了预处理语句。我使用Hibernate来执行上述查询。

     <persistence-unit name="policyPersistence" transaction-type="JTA">
      <jta-data-source>java:jboss/datasources/MyApp</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="validate" />
         <property name="hibernate.show_sql" value="false" />
         <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
         <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
      </properties>
   </persistence-unit>

JPA

query.setParameter(1, "%" + searchCriteria.getSoftwareName() + "%");

但是Postgres不能正确地转义反斜线。如何解决?
2个回答

8

与普通字符串字面量不同,反斜杠确实充当转义字符,修改 standard_conforming_strings 不会改变这一点。

为了能够使用 LIKE 搜索 %_,可以使用 escape 子句:where x like '%#_' escape '#',其中定义字符 # 作为 like 条件的转义字符。转义字符后面的任何字符都不会被解释为通配符。因此,like '%#_' escape '#' 搜索以下划线结尾的值。

反斜杠是默认的转义字符,因此不指定 escape 子句与指定 escape '\' 是相同的(这种行为是由 SQL 标准定义的)。

因此,您需要使用:

select *
from stuff.foo
where software_name like '%\%' escape '#'

为了防止Postgres使用\作为转义符,唯一的另一种方法是使用'%\\%'进行反斜杠转义(注意:这里只有两个反斜杠,而不是TimoSta建议的四个)。以下是Postgres手册链接:
http://www.postgresql.org/docs/current/static/functions-matching.html#FUNCTIONS-LIKE

转义字符 '#' 的意义是什么?为什么要用 '#'? - emeraldhieu
1
@Emerald214:就像我所写的那样:它定义了在like条件中使用的转义字符。它“禁用”了反斜杠作为转义字符的处理。您可以使用任何不太可能成为值字符串一部分的字符(更准确地说:任何不太可能在SQL通配符字符之前出现的字符)。 - user330315
啊哈,明白了!非常感谢。鼓掌鼓掌 - emeraldhieu
一个参考文档会很有帮助... :) - Nick Grealy
@NickGrealy:谢谢,好主意。我添加了一个链接到Postgres手册。你的链接是关于HQL / JPQL的,这是完全不同的,遵循不同的语法规则。我不会将其发布为SQL问题的参考。 - user330315
@a_horse_with_no_name - 太好了,是的,我只是随便找了第一个链接。好多了! - Nick Grealy

2

这应该可以正常工作:

SELECT h.software_id,
       h.software_name
FROM software h
WHERE software_name LIKE '%\\\\%';

反斜杠是SQL中LIKE子句和字符串的转义前缀,因此需要进行双重转义。


更新了问题。实际上,我只想将 '' 传递到查询中。JPA或任何库或代码片段都应该完成其余部分(转义等)。 - emeraldhieu
反斜杠在“一般字符串”中不是转义字符(Postgres中有一个设置可以打开这种非标准和已弃用的行为,但强烈建议不要这样做)。 - user330315

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接