【问题标题】:Java passing values into IN in sql WHERE clause [duplicate]Java在sql WHERE子句中将值传递给IN [重复]
【发布时间】:2018-06-22 17:16:56
【问题描述】:

我有一个类似的 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 uninmplemented or unreasonable conversion 这样的错误。

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

【问题讨论】:

  • 简单地将 List 传递到 IN 子句中,即将参数转换为 List 而不是带有逗号的单个字符串。
  • 你应该传递一个Set<String>
  • 这更像是一个 SQL 问题而不是 Java 问题。但问题是您需要与参数一样多的问号?。因此,您每次使用时都需要创建 PreparedStatement。
  • 我的参数是一个字符串链,看起来像 param = '12','34', '444' 我相信你在做这样的事情时正在检查 SQL 注入之类的东西?
  • 与您的问题无关,但使用where id in (?) 将获得比现在更好的性能。

标签: java sql oracle jdbc where-in


【解决方案1】:

您必须为 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); 
}

【讨论】:

  • to_char(id) in ('?', '?', '?', '?') 确定没有单引号?
  • 通常它根本不带引号(单引号或双引号),除了围绕整个查询的引号。
  • @Joe C 在 SQL 方面肯定。
【解决方案2】:

首先你应该知道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 子句的参数数量是动态的。

希望这会有所帮助。

【讨论】:

  • 谢谢,但我的表有几百万条记录
  • 表的大尺寸在这里不是问题。如果逗号分隔的 id 数量增长过大,性能可能会很差。在任何情况下,使用 IN 子句都会损害性能。
猜你喜欢
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-13
  • 2021-12-07
  • 2020-04-23
  • 2012-08-08
  • 2013-05-13
相关资源
最近更新 更多