更新语句的 JDBC 占位符限制的解决方法失败

Posted

技术标签:

【中文标题】更新语句的 JDBC 占位符限制的解决方法失败【英文标题】:Workaround for JDBC Limitation on Placeholders Fails for Update Statements 【发布时间】:2013-05-16 00:36:18 【问题描述】:

我正在实现一种模式来解决 JDBC 限制。对于准备好的语句,JDBC 将占位符的数量限制为 2100。为了解决这个问题,我使用了一个包含 2100 多个值的 xml 字符串,并使用函数 tf_splitxml 在 SQL Server 端解析它。我正在为 ~4 个使用准备好的语句的 Java 方法执行此操作。

这个 tf_splitxml 只是构造一个包含所有值的单列“令牌”。所以一个xml字符串:

'<node><value>1</value><value>2</value></node>' 

将转换为包含两行的列,其值为 1 和 2。

这种模式似乎适用于 select 语句,但不适用于 update 语句。这是一般模式:

declare @xml xml; set @xml = ?; --Replaced with xml string in PreparedStatement

update tableX
...
where ids in (select token from tf_splitxml(@xml));

它告诉我在将 nvarchar 值转换为数据类型 int 时转换失败。 [对于上述 xml 字符串]。奇怪的是,如果我提取prepared statement设置的查询,我可以在SQL Server中完美运行!

我的想法:

    在 4 种方法中,3 种使用这种 xml 模式;这 3 个都是 select 语句并使用 executeQuery()。第 4 个失败的方法是更新语句并使用 executeUpdate()。也许问题与prepared statement预编译sql的方式有关?

我尝试过的事情:

    我创建了一个表,可以保存从 tf_splitxml 生成的令牌。对于失败的方法,在 JDBC 抛出错误之前永远不会调用 tf_splitxml。

    在 Java 端,我使用的是 ps.setString(index, convertToXML(idsArray))。这适用于前 3 种方法,即使我的 @xml 不是字符串(它被声明为 xml 变量)。我尝试将其切换到 SQLXML 对象,但无济于事。我仍然可以正常使用相同的 3/4 方法。

    我可以直接在我的 SQL Server 编辑器中运行所有准备好的查询。

提前致以最诚挚的谢意! :)

【问题讨论】:

jdbc 对占位符的数量没有指定限制;它是您的特定驱动程序或数据库。 对不起,我的意思是 SQLServer。你是对的马克。 :) 【参考方案1】:

该代码看起来很疯狂,请查看我的ChunkWorkTemplate。这是一个简单的例子:

public void delete(final List<Integer> employeeIds) 
  new ChunkWorkTemplate<Integer>(50, employeeIds) 
    protected void executeOnChunk(List<Integer> chunk) 
      Session session = getSession();
      Query query = session.createSQLQuery("delete from Employee where employeeId in (:employeeIds)");
      query.setParameterList("employeeIds", chunk);
      query.executeUpdate();
    
  .execute();

请注意,模板的第一个参数是块大小,您可以将其设置为您喜欢的任何值。基本上,它会将输入集合分块并分块执行主体。因此,在上面的示例中,如果您有 207 个员工 ID,块大小为 50,您将有 5 个块 (50+50+50+50+7)。我写这篇文章是为了解决您面临的确切问题。希望这会有所帮助。

【讨论】:

嗨乔纳森!感谢您的输入。是的,这适用于我可以分块的情况。但是,如果我说:select * from tableA inner join tableB 嗨乔纳森!感谢您的输入。这仅适用于我可以分块的情况。如果我在多个连接表上执行 select 语句,您可能会遇到多个问题: 1. 批处理,这也会遇到重复处理。 2.返回错误数据。 (对于 NOT IN 子句,分块并不容易。)

以上是关于更新语句的 JDBC 占位符限制的解决方法失败的主要内容,如果未能解决你的问题,请参考以下文章

SQl语句中使用占位符的优点

请问下在java jdbc中:sql语句中含有or 时,该如何为这个占位符(?)赋值····求解 如下图:

解决关于配置文件的占位符无法读取问题

传统JDBC的弊病和mybatis的解决方案

廖雪峰Java15JDBC编程-3JDBC接口-2JDBC更新

MYSQL 之 JDBC: PreparedStatement