zoukankan      html  css  js  c++  java
  • 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):

    1 SELECT * FROM xxx x  
    2          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子句中的参数来自于另一张表的话,可以考虑类似如下的查询方式:

    1 SELECT * FROM xxx x
    2          INNER JOIN yyy y ON x.id = y.id   
    3          WHERE x.date <= :today 

         对于第二种方案,分批来查询速度没有第一种快,但是不用修改SQL语句。

    1         List<Item> result = Lists.newArrayList();
    2         List<List<String>> partitionIds = Lists.partition(ids, BATCH_SIZE);
    3         for (List<String> partitionId : partitionIds) {
    4             param.put("list", partitionId);
    5             List<Item> resultItems = xxxService.query(param);
    6             result.addAll(resultItems);
    7         }
    8         return result;

         这种方案的劣势在于速度上会有损失,但是可以从Java代码的逻辑层避免上面的问题。

         希望这些对大家有所帮助。


  • 相关阅读:
    微信小程序HTTPS
    微信商城-1简介
    va_list
    Event log c++ sample.
    EVENT LOGGING
    Analyze Program Runtime Stack
    unknow table alarmtemp error when drop database (mysql)
    This application has request the Runtime to terminate it in an unusual way.
    How to check if Visual Studio 2005 SP1 is installed
    SetUnhandledExceptionFilter
  • 原文地址:https://www.cnblogs.com/penghongwei/p/3603872.html
Copyright © 2011-2022 走看看