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
子句的参数数量是动态的。
希望这对您有所帮助。
我有一个 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
子句的参数数量是动态的。
希望这对您有所帮助。