Java 无法在JDBC PreparedStatement中使用LIKE查询?

Java 无法在JDBC PreparedStatement中使用LIKE查询?,java,oracle,jdbc,sql-like,Java,Oracle,Jdbc,Sql Like,查询代码和查询: ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2"); ps.setString(1,"SUBSTR(DSN,27,16)"); ps.setI

查询代码和查询:

ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2");
ps.setString(1,"SUBSTR(DSN,27,16)");
ps.setInt(2,defaultWasGroup);
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%");
rs = ps.executeQuery();
while (rs.next()) { bla blah blah blah ...
返回一个空的
结果集

通过基本的调试,我发现了问题的第三个绑定,即

DSN like '?'
我尝试过各种变化,其中最明智的似乎是使用:

DSN like concat('%',?,'%')
但这不起作用,因为我缺少连接字符串两侧的
,因此我尝试:

DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2
但我似乎找不到办法让他们这么做


我遗漏了什么?

省略
周围的
。如果没有
是参数的占位符。它是一个SQL字符串(即与Java中的
“?”
相同)


然后必须在Java端连接字符串;不能将SQL函数作为参数传递给查询;仅使用基本值(如字符串、整数等),因为JDBC驱动程序将参数转换为数据库所需的SQL类型,并且在此步骤中无法执行SQL函数。

您的语句有两个问题。您必须了解绑定变量是如何工作的。查询未通过用参数替换字符
进行处理。相反,使用占位符编译语句,然后在执行期间,将参数的实际值提供给DB

换句话说,您将解析以下查询:

SELECT instance_id, :p1
  FROM eam_measurement
 WHERE resource_id IN (SELECT RESOURCE_ID 
                         FROM eam_res_grp_res_map 
                        WHERE resource_group_id = :p2)
   AND DSN LIKE '?'
 ORDER BY 2
SELECT instance_id, 'SUBSTR(DSN,27,16)'
  FROM ...
我很确定最后一个参数将被忽略,因为它位于分隔字符串中。即使它没有被忽略,也没有必要使用
字符,因为Oracle不会将参数绑定到字符串中(我很惊讶它没有引发任何错误,是否捕获异常?)

现在,如果您用类似DSN的
DSN?
替换类似DNS的“?”
,并绑定
%Module=jvmRuntimeModule:freeMemory%”
这将有意义,并应返回正确的行

您的第一个参数仍然存在问题,它不会执行您期望的操作,即将执行的查询将等效于以下查询:

SELECT instance_id, :p1
  FROM eam_measurement
 WHERE resource_id IN (SELECT RESOURCE_ID 
                         FROM eam_res_grp_res_map 
                        WHERE resource_group_id = :p2)
   AND DSN LIKE '?'
 ORDER BY 2
SELECT instance_id, 'SUBSTR(DSN,27,16)'
  FROM ...
这与

SELECT instance_id, SUBSTR(DSN,27,16)
  FROM ...
如果您希望SUBSTR是动态的,我建议您解析(=prepareStatement)以下查询:

SELECT instance_id, SUBSTR(DSN,?,?)
  FROM eam_measurement
 WHERE resource_id IN (SELECT RESOURCE_ID 
                         FROM eam_res_grp_res_map 
                        WHERE resource_group_id = ?)
   AND DSN LIKE ?
 ORDER BY 2

首先,
PreparedStatement
占位符(那些
东西)仅用于列值,而不用于表名、列名、SQL函数/子句等。最好改用。其次,您应该而不是引用像
“?”
这样的占位符,这只会使最终的查询格式不正确。
PreparedStatement
setter已经为您完成了引用(和转义)工作

以下是固定SQL:

private static final String SQL = "select instance_id, %s from eam_measurement"
    + " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where"
    + " resource_group_id = ?) and DSN like ? order by 2");
以下是如何使用它:

String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s.
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, defaultWasGroup);
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%");

另见

您可以尝试:

String beforeAndAfter = "%" + yourVariable + "%";

如果您希望在准备好的语句中使用LIKE,并且还希望在LIKE中使用%个字符

正常情况下,编写准备好的语句“…像?…”,并在为问号指定参数值时使用

ps.setString(1,“%”+“您的字符串值”+“%”)

这将起作用:)

这将起作用:

"\'" + "?" + "\'"

这里的
var
是存储要搜索的值的变量…

是否在变量周围没有“”?我也得到了一个空的结果集。毫不奇怪,我猜sql会读到:和DSN一样的%Module=P_STAG_JDBC01:poolSize%,oracle不喜欢它,并回答:在索引::1处缺少IN或OUT参数(错误代码=17041),因此当我通过ps.setString设置绑定时,我需要向绑定添加“s”,例如ps.setString(3,“'Module=jvmRuntimeModule:freemory'”;但也会给出一个空结果集,ps.setString(3,“\'Module=jvmRuntimeModule:freemory\”)也是如此;尽管java文档称不必转义“内部”s@SeerUK:错误消息来自参数1,而不是参数3!在JSP文件中而不是在真正的Java类中编写Java代码(您应该在Java类中编写Java代码),并且在特定Java代码中遇到问题并不会使其成为JSP问题。在真正的Java类中执行此操作时,您将面临完全相同的问题。因此,我删除了
[jsp]
标记,因为这与jsp无关。的确,它不是特定于jsp的,但根据我读过的大多数书籍,在servlet中使用此类代码没有什么错,特别是当它是一个超级简单的报告页面,代码不到40行,而应用程序架构有点过分:)但我很欣赏你的观点!请给出更多的解释并格式化您的代码(您可以使用“back ticks”或将其缩进4个空格)。