简体   繁体   English

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

[英]Cannot use a LIKE query in a JDBC PreparedStatement?

The query code and query: 查询代码和查询:

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 ...

Returns an empty ResultSet . 返回一个空ResultSet

Through basic debugging I have found its the third bind that is the problem ie 通过基本的调试我发现它的第三个绑定是问题,即

DSN like '?'

I have tried all kinds of variations, the most sensible of which seemed to be using: 我尝试了各种各样的变化,其中最明智的似乎是使用:

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

but that does not work as I am missing the ' on either side of the concatenated string so I try: 但这不起作用,因为我错过了连接字符串两侧的'所以我尝试:

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

but I just cannot seem to find a way to get them in that works. 但我似乎无法找到一种方法让他们参与其中。

What am I missing? 我错过了什么?

First, the PreparedStatement placeholders (those ? things) are for column values only, not for table names, column names, SQL functions/clauses, etcetera. 首先, PreparedStatement占位符(那些?事物)仅用于列值 ,而不用于表名,列名,SQL函数/子句等。 Better use String#format() instead. 最好使用String#format() Second, you should not quote the placeholders like '?' 其次,你应该引用像占位符'?' , it would only malform the final query. ,它只会使最终查询失真。 The PreparedStatement setters already do the quoting (and escaping) job for you. PreparedStatement设置器已经为您执行引用(和转义)作业。

Here's the fixed SQL: 这是修复的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");

Here is how to use it: 以下是如何使用它:

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%");

See also : 另见

If you want to use LIKE in prepared statement and also want to use % characters in LIKE; 如果要在预准备语句中使用LIKE,并且还想在LIKE中使用%字符;

write prepared statement as normally " .... LIKE ? ...." and while assigning parameter value to question mark use 将准备好的语句写成通常“.... LIKE?....”并将参数值分配给问号使用

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

This will work :) 这将工作:)

There are two problems with your statement. 你的陈述有两个问题。 You have to understand how bind variables work. 您必须了解绑定变量的工作原理。 The query is not processed by substituing the characters ? 是否通过替换字符来处理查询? with your parameters. 与您的参数。 Instead, the statement is compiled with placeholders and then, during execution, the actual values of the parameters are given to the DB. 而是使用占位符编译语句,然后在执行期间,将参数的实际值提供给DB。

In other words, you parse the following query: 换句话说,您解析以下查询:

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

I'm pretty sure the last parameter will be ignored because it is in a delimited character string. 我很确定最后一个参数会被忽略,因为它是一个分隔的字符串。 Even if it is not ignored, it does not make sense to have ' characters around because Oracle won't bind a parameter in a string (I'm surprised it hasn't raised any error, do you catch exceptions ?). 即使它没有被忽略,因为Oracle不会绑定字符串中的参数(我很惊讶它没有引发任何错误,你是否捕获异常?),因此将'字符放在周围是没有意义的。

Now if you replace your DNS LIKE '?' 现在如果你替换你的DNS LIKE '?' with DSN LIKE ? DSN LIKE ? and bind "%Module=jvmRuntimeModule:freeMemory%" this will make sense and should return the correct rows. 并绑定"%Module=jvmRuntimeModule:freeMemory%"这将是有意义的,应该返回正确的行。

You still have the problem with your first parameter, it won't do what you expect, ie the query that will be executed will be equivalent to the following query: 您仍然遇到第一个参数的问题,它不会按预期执行,即将执行的查询将等同于以下查询:

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

which is not at all the same as 这与...完全不一样

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

I would suggest parsing (=prepareStatement) the following query if you expect the SUBSTR to be dynamic: 如果您希望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

Omit the ' around the ? 省略'围绕? . Without the ' , ? 没有'? is a placeholder for a parameter. 是参数的占位符。 With it, it's an SQL string (ie the same as "?" in Java). 有了它,它是一个SQL字符串(即与Java中的"?"相同)。

Then you must concatenate the string on the Java side; 然后你必须连接Java端的字符串; you can't pass SQL functions as parameters to queries; 您不能将SQL函数作为参数传递给查询; only basic values (like string, integer, etc) because the JDBC driver will convert the parameter to the SQL type the database expects and it cannot execute SQL functions in this step. 只有基本值(如字符串,整数等),因为JDBC驱动程序会将参数转换为数据库所需的SQL类型,并且在此步骤中不能执行SQL函数。

你可以试试:

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

Here var is the variable in which value that is to be searched is stored... 这里var是存储要搜索的值的变量...

这应该工作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM