2010-05-18 87 views
26

查询码和查询:无法在JDBC PreparedStatement中使用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.setInt(2,defaultWasGroup); 
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%"); 
rs = ps.executeQuery(); 
while (rs.next()) { bla blah blah blah ... 

返回一个空ResultSet

通过基本的调试,我发现它的第三绑定即即

DSN like '?' 

我已经尝试了各种变化,这是最明智的似乎的问题可以用:

DSN like concat('%',?,'%') 

但这不起作用,因为我在连接字符串的任一侧上缺少',所以我尝试:

DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2 

但我似乎无法找到一种方法让他们在作品中。

我错过了什么?

+0

将Java代码写入JSP文件而不是写入真正的Java类(您应**已经完成它),并且遇到问题特定的Java代码不会使其成为JSP问题。在真正的Java类中这样做时,您将面临完全相同的问题。所以我删除了'[jsp]'标签,因为这是无关紧要的。 – BalusC 2010-05-18 12:52:36

+1

真的,它不是JSP特定的,但是根据我读过的大多数书籍,在servlet中使用这样的代码没有什么错误,特别是当它是一个超过40行代码的超级简单报告页面时,应用程序体系结构是有点矫枉过正:)但我很感谢你的观点! – SeerUK 2010-05-18 13:12:02

回答

52

首先,PreparedStatement占位符(那些?东西)仅适用于列值,不适用于表名称,列名,SQL函数/子句等等。改用String#format()代替。其次,你应该不是引用像'?'的占位符,它只会malformed最终查询。 PreparedStatement制定者已经为你做了引用(和转义)工作。

这里是固定的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%"); 

参见

2

省略'围绕?。没有'?是参数的占位符。有了它,它就是一个SQL字符串(即与Java中的"?"相同)。

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

+0

没有“'围绕?我也得到一个空的resultSet。毫不奇怪,我猜测那么sql会读取:和DSN类似于%Module = P_STAG_JDBC01:poolSize%,oracle不喜欢并回复:在index :: 1处缺少IN或OUT参数(错误代码= 17041)因此,我需要当我通过ps.setString设置它时,添加''到绑定? – SeerUK 2010-05-18 12:37:47

+0

例如 ps.setString(3,''Module = jvmRuntimeModule:freeMemory'“); 但也给出了一个空的结果集,如同 ps.setString(3,“\'Module = jvmRuntimeModule:freeMemory \'”); 虽然java文档说,它不应该有必要转义'内部's – SeerUK 2010-05-18 12:39:42

+0

@ SeerUK:错误信息来自参数1,而不是参数3! – 2010-05-18 14:31:25

10

您的陈述有两个问题。你必须了解绑定变量是如何工作的。查询是未通过用您的参数代替字符?进行处理。而是使用占位符编译语句,然后在执行过程中将参数的实际值赋予数据库。

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

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 

我敢肯定最后一个参数会被忽略,因为它是一个分隔符的字符串。即使它没有被忽略,因为Oracle不会绑定字符串中的参数(我很惊讶它没有引发任何错误,您是否捕获异常?),因此在字符周围设置字符是没有意义的。

现在,如果您将DNS LIKE '?'替换为DSN LIKE ?,并绑定"%Module=jvmRuntimeModule:freeMemory%",这将有意义并应返回正确的行。

你仍然有你的第一个参数的问题,它不会做你所期望的,也就是将要执行的查询将等同于以下查询:

SELECT instance_id, 'SUBSTR(DSN,27,16)' 
    FROM ... 

这是不是在所有同

SELECT instance_id, SUBSTR(DSN,27,16) 
    FROM ... 

我建议解析(= prepareStatement)下面的查询,如果你希望在SUBSTR是动态的:

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 
0

你可以试试:

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

如果你想在事先准备好的声明中使用等,还希望喜欢用%字符;

写事先准备好的声明为常“......怎么样?......”,虽然分配的参数值,以问号使用

ps.setString(1, "%" + "your string value" + "%");

这将工作:)

0

这应该工作:

"\'" + "?" + "\'" 
0
PreparedStatement ps = con.prepareStatement(
    "select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')"); 

这里var是存储要查找的值的变量...

+1

请给出更多的解释和格式化您的代码(您可以使用“倒勾”或缩进4个空格)。 [如何回答](http://stackoverflow.com/help/how-to-answer) – AgataB 2016-09-10 11:09:28