在IN子句中包含数千个参数的PreparedStatement

时间:2013-03-14 02:41:56

标签: java sql sql-server sql-server-2005 jdbc

我确实从这个问题PreparedStatement IN clause alternatives?中读到了解决方案。但就我而言,我在一个In子句中有大约5000个参数,它会导致java.sql.SQLException:Prepared或callable语句有超过2000个参数标记。

我使用的是像

这样的SQL
String sql = "select * from project in " + projectIds.toString() 

projectIds是一个StringBuilder,就像“(1,2,3,4 ......)”但是代码安全报告说它可能导致sql注入。所以我必须使用?占位符以避免它。

我尝试使用

String sql = "select * from project where charindex(','+convert(varchar(max),id)+',', ?)>0";
statement.setString(1,projectIds.toString);//projectIds like ",1,2,3,4,"..

但最终会出现错误的语法错误。

有没有解决方案?

3 个答案:

答案 0 :(得分:2)

Hogan建议使用表格是一个很好的建议。我唯一要改变的是查询,因为JOIN为tablelist中的每个值生成一行。相反(猜测你的列名)

select * from project 
where projectID in (select id from tablelist)

where exists (select 1 from tablelist where id = projectID)

答案 1 :(得分:1)

执行此操作的最佳方法是不使用in语句。相反,您应该将要检查的所有值放在表中并使用连接。

例如,如果您有一个包含列的表(名为id)的表,那么您的语句将如下所示:

 select *
 from project
 join tablelist on project.project = tablelist.id

这会快得多,因为SQL服务器非常擅长快速执行连接。


您也可以使用CTE执行此操作。例如:

WITH tablelist as
(
   SELECT 1 AS id
   UNION ALL
   SELECT 3
   UNION ALL
   SELECT 4
   UNION ALL
   SELECT 5
   UNION ALL
   SELECT 6
   UNION ALL
   SELECT 7
   // More if needed
)
select *
from project
join tablelist on project.project = tablelist.id

这可以作为一个大查询发送并且可以工作。你的唯一限制是查询的最大大小,我不知道是否存在这样的限制。

答案 2 :(得分:1)

select * from project in " + projectIds.toString()

语法不正确,应该是

select * from project where id in (" + projectIds + ")";