Java 在 sql WHERE 子句中将值传递到 IN

Java passing values into IN in sql WHERE clause

我有一个 sql 查询

(sqlQuery)
SELECT *
FROM table1
WHERE to_char(id) in (?)

然后在我准备好的声明中

preparedStatement ps = new preparedStatemend(sqlQuery)
ps.setString(1,param);

我的参数是一个看起来像 param = '12','34', '444'

的字符串链

现在,我以为当我执行它时一切都会好起来的,但事实并非如此,我得到了类似 ORA 01460 未实现或不合理转换的错误。

那么,如何将包含一些值的参数传递到 sql 查询中的 IN 子句中?

您必须为 IN 子句的每个可能值指定一个 ?

例如,如果您在 IN 子句中有 4 个可能的选项,则此 :

to_char(id) in (?)

应该是:

to_char(id) in (?, ?, ?, ?) 

并且您还应该通过连续递增要设置的参数的索引来设置每个参数:

所以这个 :

ps.setString(1,param);

应该是:

int index = 1;
for( String s : inValues ) {
   ps.setString(index++, s); 
}

首先你应该知道IN子句中的数据是有限制的。因此,如果您有大量逗号分隔值作为 IN 子句的参数(绑定变量)传​​递,您应该管理其他内容。

现在,如果您的 ID 数量有限(例如少于 500 个左右,取决于 ID 的大小,完全不能超过 4000 个字符),您可以使用 regexp_substr 以及connect by 标记 where 子句中单个参数 ? 的逗号分隔值:to_char(id) in (?) :

 SELECT REGEXP_SUBSTR(? ,'[^,]+', 1, LEVEL) FROM dual
CONNECT BY REGEXP_SUBSTR(? , '[^,]+', 1, LEVEL) IS NOT NULL

当您将字符串 "'12','34', '444'" 作为参数传递时,它会将它们标记为行:

'12'

'34'

'444'

所以理论上你可以这样改变你的查询:

SELECT *
  FROM table1
 WHERE to_char(id) in 
 (
       SELECT REGEXP_SUBSTR(? ,'[^,]+', 1, LEVEL) FROM dual
      CONNECT BY REGEXP_SUBSTR(? , '[^,]+', 1, LEVEL) IS NOT NULL
 )

但是 如果 table1 的大小很大,性能会很差,因为每个 id 的转换记录。

最好转换你有限数量的IN子句参数以提高性能:

SELECT *
  FROM table1
 WHERE id in 
 (
       SELECT REGEXP_SUBSTR(? ,'[^,]+', 1, LEVEL) FROM dual
      CONNECT BY REGEXP_SUBSTR(? , '[^,]+', 1, LEVEL) IS NOT NULL
 )

并且在您的 java 代码中,您应该将字符串 "12,34, 444" 作为参数传递(每个 ID 两边没有单引号)。

您应该知道,此解决方案并未针对大量 ID 进行优化。但是,它使 IN 子句的参数数量是动态的。

希望这对您有所帮助。