在java.sql实例中使用SQL IN子句的最佳变通方法是什么?由于SQL注入攻击安全问题,不支持多值的PreparedStatement:一个?占位符表示一个值,而不是一个值列表。
考虑下面的SQL语句:
SELECT my_column FROM my_table where search_column IN (?)
使用preparedStatement。setString(1, "'A', 'B', 'C'");本质上是一种无用的尝试,试图解决使用原因?首先。
有什么可行的解决办法?
在研究了不同论坛上的各种解决方案后,没有找到一个好的解决方案,我觉得下面的方法是最容易遵循和编码的:
示例:假设您有多个参数要传递到' in '子句中。只要在'IN'子句中放入一个虚拟字符串,例如,“PARAM”确实表示将在这个虚拟字符串中出现的参数列表。
select * from TABLE_A where ATTR IN (PARAM);
您可以在Java代码中将所有参数收集到一个String变量中。可以这样做:
String param1 = "X";
String param2 = "Y";
String param1 = param1.append(",").append(param2);
你可以将所有用逗号分隔的参数附加到一个String变量中,在我们的例子中是'param1'。
在将所有参数收集到单个字符串中之后,您可以将查询中的虚拟文本替换为参数String,即param1,在本例中为“PARAM”。以下是你需要做的:
String query = query.replaceFirst("PARAM",param1); where we have the value of query as
query = "select * from TABLE_A where ATTR IN (PARAM)";
现在可以使用executeQuery()方法执行查询。只要确保在查询中没有“PARAM”这个词。您可以使用特殊字符和字母的组合来代替单词“PARAM”,以确保查询中不可能出现这样的单词。希望你得到了答案。
注意:虽然这不是一个准备好的查询,但它完成了我希望代码完成的工作。
SetArray是最好的解决方案,但它不适用于许多老司机。下面的解决方法可以在java8中使用
String baseQuery ="SELECT my_column FROM my_table where search_column IN (%s)"
String markersString = inputArray.stream().map(e -> "?").collect(joining(","));
String sqlQuery = String.format(baseSQL, markersString);
//Now create Prepared Statement and use loop to Set entries
int index=1;
for (String input : inputArray) {
preparedStatement.setString(index++, input);
}
这个解决方案比其他难看的while循环解决方案好,其中查询字符串是通过手动迭代构建的
尝试使用instr函数?
select my_column from my_table where instr(?, ','||search_column||',') > 0
then
ps.setString(1, ",A,B,C,");
不可否认,这是一个肮脏的黑客,但它确实减少了sql注入的机会。在甲骨文工作。