使用 SQL 的最佳解决方法是什么 IN
具有 java.sql.PreparedStatement
实例的子句,由于 SQL 注入(inject)攻击安全问题,不支持多个值:1 ?
占位符代表一个值,而不是一组值。
考虑以下 SQL 语句:
SELECT my_column FROM my_table where search_column IN (?)
使用preparedStatement.setString( 1, "'A', 'B', 'C'" );
本质上是对使用?
原因的解决方法的非工作尝试。首先。
有哪些可用的解决方法?
最佳答案
Jeanne Boyarsky 的 Batching Select Statements in JDBC 中提供了对各种可用选项及其优缺点的分析。 JavaRanch Journal 上的条目。
建议的选项是:
- 准备
SELECT my_column FROM my_table WHERE search_column = ?
,对每个值执行它并在客户端对结果进行 UNION。仅需要一份准备好的声明。缓慢而痛苦。 - 准备
SELECT my_column FROM my_table WHERE search_column IN (?,?,?)
并执行它。每个 size-of-IN-list 需要一个准备好的语句。快速且明显。 - 准备
SELECT my_column FROM my_table WHERE search_column = ? ; SELECT my_column FROM my_table WHERE search_column = ? ; ...
并执行它。 [或使用UNION ALL
代替那些分号。 --ed] 每个 size-of-IN-list 需要一个准备好的语句。慢得愚蠢,严格来说比WHERE search_column IN (?,?,?)
还要差,所以我不知道博主为什么这么建议。 - 使用存储过程构建结果集。
- 准备N个不同大小的IN列表查询;例如,具有 2、10 和 50 个值。要搜索具有 6 个不同值的 IN 列表,请填充 size-10 查询,使其看起来像
SELECT my_column FROM my_table WHERE search_column IN (1,2,3,4,5,6,6,6,6,6)
。任何像样的服务器都会在运行查询之前优化重复值。
这些选项都不理想。
如果您使用 JDBC4 和支持 x = ANY(y)
的服务器,这是最佳选择,就是使用PreparedStatement.setArray
如 Boris's anwser 中所述.
似乎没有办法制作setArray
不过,可以使用 IN 列表。
有时 SQL 语句在运行时加载(例如,从属性文件),但需要可变数量的参数。在这种情况下,首先定义查询:
query=SELECT * FROM table t WHERE t.column IN (?)
接下来,加载查询。然后在运行之前确定参数的数量。一旦知道参数计数,请运行:
sql = any( sql, count );
例如:
/**
* Converts a SQL statement containing exactly one IN clause to an IN clause
* using multiple comma-delimited parameters.
*
* @param sql The SQL statement string with one IN clause.
* @param params The number of parameters the SQL statement requires.
* @return The SQL statement with (?) replaced with multiple parameter
* placeholders.
*/
public static String any(String sql, final int params) {
// Create a comma-delimited list based on the number of parameters.
final StringBuilder sb = new StringBuilder(
String.join(", ", Collections.nCopies(possibleValue.size(), "?")));
// For more than 1 parameter, replace the single parameter with
// multiple parameter placeholders.
if (sb.length() > 1) {
sql = sql.replace("(?)", "(" + sb + ")");
}
// Return the modified comma-delimited list of parameters.
return sql;
}
对于某些不支持通过 JDBC 4 规范传递数组的数据库,此方法可以帮助转换缓慢的 = ?
进得更快IN (?)
子句条件,然后可以通过调用 any
来扩展该条件方法。
关于java - PreparedStatement IN 子句替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46442229/