不能在JDBC PreparedStatement中使用LIKE查询?

时间:2010-05-18 12:24:10

标签: 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.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

但我似乎无法找到让他们参与其中的方法。

我错过了什么?

7 个答案:

答案 0 :(得分:58)

首先,PreparedStatement占位符(那些?内容)仅适用于列值,而不适用于表名,列名,SQL函数/子句等。更好地使用String#format()。其次,你应该引用像'?'这样的占位符,它只会使最终查询失真。 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%");

另见

答案 1 :(得分:11)

您的陈述有两个问题。您必须了解绑定变量的工作原理。查询未通过使用您的参数替换字符?来处理。而是使用占位符编译语句,然后在执行期间,将参数的实际值提供给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

我很确定最后一个参数会被忽略,因为它是一个分隔的字符串。即使它没有被忽略,因为Oracle不会绑定字符串中的参数(因为Oracle没有引发任何错误,你是否捕获异常,因此没有'个字符是没有意义的。 )。

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

您的第一个参数仍然存在问题,它不会达到您的预期,即,将要执行的查询将等同于以下查询:

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

答案 2 :(得分:11)

如果要在预准备语句中使用LIKE,并且还想在LIKE中使用%字符;

将准备好的语句写成通常“.... LIKE?....”并将参数值分配给问号使用

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

这将有效:)

答案 3 :(得分:2)

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

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

答案 4 :(得分:0)

您可以尝试:

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

答案 5 :(得分:0)

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

此处var是存储要搜索的值的变量...

答案 6 :(得分:-1)

这应该有效:

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