java.sql.SQLException: Prepared or callable statement has more than 2000 parameter markers及解决方案
1. 问题
最近在项目中修bug的时候,碰到这样一个错误:
Caused by: java.sql.SQLException:Prepared or callable statement has more than 2000 parameter markers. at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:1139)
at net.sourceforge.jtds.jdbc.SQLParser.parse(SQLParser.java:156)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.<init>(JtdsPreparedStatement.java:107) Caused by: java.sql.SQLException:Prepared or callable statement has more than 2000 parameter markers.
出错的代码简化如下(list中的元素个数可能大于2000):
SELECT * FROM xxx x
WHERE x.date <= :today AND x.id IN (:list)
2. 收获
起初并不明白是什么情况,经过一番google加请教之后,有一些收获。项目中用的JTDS的driver版本为1.2.4,数据库为SQL Server。在该driver的源码中找到如下一个片段(在net.sourceforge.jtds.jdbc.SQLParser类中):

从这段代码中可以看出,其实这并不是一个bug,而是work as designed。我们得到的另一个信息是,对于不同类型的数据库,不同的版本之间,这种约束是有差别的,分别是255,1000,2000。这样看来,之前的查询语句出错也就很好理解了,在IN子句中的参数个数多于2000是肯定会抛异常的。
3. 解决方案
主要有两种解决方案:一种是优化SQL语句,一种是优化查询逻辑(即分批处理)。
对于第一种方案,如果IN子句中的参数来自于另一张表的话,可以考虑类似如下的查询方式:
SELECT * FROM xxx x
INNER JOIN yyy y ON x.id = y.id
WHERE x.date <= :today
对于第二种方案,分批来查询速度没有第一种快,但是不用修改SQL语句。
List<Item> result = Lists.newArrayList();
List<List<String>> partitionIds = Lists.partition(ids, BATCH_SIZE);
for (List<String> partitionId : partitionIds) {
param.put("list", partitionId);
List<Item> resultItems = xxxService.query(param);
result.addAll(resultItems);
}
return result;
这种方案的劣势在于速度上会有损失,但是可以从Java代码的逻辑层避免上面的问题。
希望这些对大家有所帮助。
java.sql.SQLException: Prepared or callable statement has more than 2000 parameter markers及解决方案的更多相关文章
- HiveServer2 的jdbc方式创建udf的修改(add jar 最好不要使用),否则会造成异常: java.sql.SQLException: Error while processing statement: null
自从Hive0.13.0开始,使用HiveServer2 的jdbc方式创建udf的临时函数的方法由: ADD JAR ${HiveUDFJarPath} create TEMPORARY funct ...
- java.sql.SQLException: Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
执行Hive查询: Console是这样报错的 java.sql.SQLException: Error from org.apache.hadoop.hive.ql.exec.mr.MapRedTa ...
- java.sql.SQLException: The SQL statement must not be null or empty.这个错误
今天发现了这个错误 java.sql.SQLException: The SQL statement must not be null or empty. 并且看了些网页:综合说下这个错误. 一般都是 ...
- 在mybatis中使用存储过程报错java.sql.SQLException: ORA-06550: 第 1 行, 第 7 列: PLS-00905: 对象 USER1.HELLO_TEST 无效 ORA-06550: 第 1 行, 第 7 列:
hello_test是我的存储过程的名字,在mapper.xml文件中是这么写的 <select id="getPageByProcedure" statementType= ...
- Oracle java.sql.SQLException: 数字溢出
六月 30, 2016 5:47:47 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinit ...
- java.sql.SQLException: 对只转发结果集的无效操作: last
出错代码如下:static String u = "user";static String p = "psw";static String url = &quo ...
- Hive报错之java.sql.SQLException: Field 'IS_STOREDASSUBDIRECTORIES' doesn't have a default value
在创建表的时候报出如下错误: hive> create table if not exists testfile_table( > site string, > url string ...
- java.sql.SQLException: Lock wait timeout exceeded --转
org.springframework.dao.CannotAcquireLockException 的解决> 直接上 bug 的详细信息: 2012-03-12 15:20:31 XmlBea ...
- java.sql.SQLException: Before start of result set
在使用JDBC查询数据库报了这么一个错误 CREATE TABLE `d_user` ( `id` int(10) NOT NULL, `name` varchar(10) DEFAULT NULL, ...
随机推荐
- css3 动画效果实现
前沿 在工作中,经常有一些需要切换的交互样式.如果直接在两种状态之间切换,就显得有点生硬.加上一些动画效果就会好很多. 示例1:点击的三角切换 实现过程 第一步实现这个三角形 用的svg 的多边形画法 ...
- Python-str-操作-6
#字符串的索引与切片 s = 'ABCDLSESRF' #索引 s1 = s[0] print(s1) s2 = s[2] print(s2) s3 = s[-1] print(s3) s4 = s[ ...
- iOS APP 中H5视频默认全屏播放问题解决
问题描述:在Android中,视频可以正常在H5页面局部播放,iOS中则自动切换至全屏模式. 查看资料得以解决,20190301记录下来. 解决方法:IOS10及以后,在 video标签页中只包含 w ...
- Tor源码阅读与改造(一)
0x00 前言 由于公司需求,需要掌握洋葱网络的整体架构和部分详细实现细节,并对Tor进行针对性的改造.在查询Tor官方相关文档和google各种网站后,得到的信息仍无法达到目的,所以便开始了阅读To ...
- 传输层中的协议 TCP & UDP
面向连接的TCP协议 “面向连接”就是在正式通信前必须要与对方建立起连接.比如你给别人打电话,必须等线路接通了.对方拿起话筒才能相互通话.TCP(Transmission Control Protoc ...
- Angular 简单的Get
<!DOCTYPE html><html ng-app="myApp"><head lang="en"> <meta ...
- ubuntu安装命令
sudo apt-get update 更新源sudo apt-get install package 安装包sudo apt-get remove package 删除包sudo apt-cach ...
- 关于一个常用的CheckBox样式
我们在使用CheckBox的时候,原始的样式有时不能满足我们的需求,这是我们就需要更改其模板,比如我们常用的一种,在播放器中“播放”.“暂停”按钮,其实这也是一种CheckBox,只不过我们只是修改了 ...
- linux bin & sbin different
linux bin & sbin different flutter & $PATH http://blog.taylormcgann.com/2014/04/11/differenc ...
- String在内存中如何存储(Java)
JDK1.8中JVM把String常量池移入了堆中,同时取消了“永久代”,改用元空间代替(Metaspace)java中对String对象特殊对待,所以在heap区域分成了两块,一块是字符串常量池(S ...