简体   繁体   English

JDBC 当要设置的列因行而异时批量使用 PreparedStatement

[英]JDBC PreparedStatement in batch when columns to set vary from row to row

I am trying to batch updates using PreparedStatement where the data you get in varies in what you have available.我正在尝试使用 PreparedStatement 批量更新,您获得的数据因可用数据而异。

Simple example:简单的例子:

You have a table with column x and y.您有一个包含 x 和 y 列的表。 Your inputdata is a representation of rows where only the modified column is present.您的 inputdata 是仅存在已修改列的行的表示形式。 So for row 1 you have x='foo' and for row 2 you have y='bar'.所以对于第 1 行,您有 x='foo',对于第 2 行,您有 y='bar'。 In order to batch these with a PreparedStatement you need one SQL statement: "update table where x=?,y=? where etc".为了使用 PreparedStatement 对这些进行批处理,您需要一个 SQL 语句:“update table where x=?,y=? where etc”。

The solution that I am working towards is setting the column where you dont have any value to the value that is already present, but I'm not sure if this is possible.我正在努力的解决方案是将没有任何值的列设置为已经存在的值,但我不确定这是否可能。 In raw SQL you could write "update table where x=x and y='foo' where etc", however I haven't found any ways to achieve this by setting the "?"在原始 SQL 中,您可以编写“update table where x=x and y='foo' where etc”,但是我还没有找到任何方法来通过设置“?”来实现这一点。 parameter to be a reference to the column, it seems it's not possible.参数作为对列的引用,似乎不可能。

Is it possible to handle this case at all with PreparedStatements?是否可以使用 PreparedStatements 来处理这种情况? I apologize if my explanation is poor.如果我的解释不好,我深表歉意。

Assuming the values you want to set are all non-null, you could use a statement like假设您要设置的值都是非空的,您可以使用如下语句

update sometable set column1 = coalesce(?, column1), colum2 = coalesce(?, column2)

Then when the value should not be updated, use either PreparedStatement.setNull with an appropriate java.sql.Types value or a PreparedStatement.setXXX of the appropriate type with a null as value.然后,当不应更新该值时,使用PreparedStatement.setNull和适当的java.sql.Types值或适当类型的PreparedStatement.setXXXnull值。

As discussed in the comments, an alternative if you do need to update to null , is to use a custom function with a sentinel value (either for updating to null or for using the current value).如评论中所述,如果您确实需要更新到null ,另一种方法是使用带有标记值的自定义 function (更新到 null 或使用当前值)。 Something like:就像是:

update sometable set column1 = conditional_update(?, column1), colum2 = conditional_update(?, column2)

Where conditional_update would be something like (using Firebird 3 PSQL syntax):其中conditional_update类似于(使用 Firebird 3 PSQL 语法):

create function conditional_update(new_value varchar(500), original_value varchar(500)) 
  returns varchar(500)
as
begin
  if (new_value = '$$NO_UPDATE$$') then
     return original_value;
  else
     return new_value;
end

Where using $$NO_UPDATE$$ is a sentinel value for not updating.其中使用$$NO_UPDATE$$是不更新的标记值。 A potential downside of this solution is the typing of columns as a string type.此解决方案的一个潜在缺点是将列键入为字符串类型。 You always need to use string types (I'm not sure if there are databases that would supports dynamic parameters and return types in this situation).您总是需要使用字符串类型(我不确定在这种情况下是否有支持动态参数和返回类型的数据库)。

Let me rephrase your problem and you please tell me if this is right: You want to be able to have the update process让我重新表述您的问题,请告诉我这是否正确:您希望能够进行更新过程

  • sometimes you only update for a specific x有时您只更新特定的 x
  • sometimes you only update for a specific y有时您只更新特定的 y
  • sometimes you update for specific x and y combined有时您会更新特定的 x 和 y 组合

Correct?正确的? If 'yes' then the next issue is implementation possibilities.如果“是”,那么下一个问题是实施可能性。

You suggested trying to put the column itself into the parameter.您建议尝试将列本身放入参数中。 Even if that's possible I'd still recommend against it.即使这是可能的,我仍然建议不要这样做。 The code will get confusing.代码会变得混乱。

I suggest you create a java method that builds and returns the query string (or at least the 'where' clause) based on your available parameters (x, y, etc) Your code for invoking the JDBC Prepared statement will invoke that method to get a query String.我建议您创建一个 java 方法,该方法根据您的可用参数(x、y 等)构建并返回查询字符串(或至少是“where”子句)您用于调用 JDBC 的代码将调用该方法来获取一个查询字符串。 You will still benefit from using prepared statements.您仍然会从使用准备好的语句中受益。 The cost is that your database will be caching several different statements instead of one, but I imagine that is a minimal issue.代价是您的数据库将缓存几个不同的语句而不是一个,但我认为这是一个最小的问题。

You can think of auxiliar "?"你能想到辅助“?” variable for each column which will manage if the column should be updated or not.每列的变量将管理列是否应该更新。

update table
set x = case when 0 = ? then x else ? end,
    y = case when 0 = ? then y else ? end
where etc;

Passing 0 for each 0 =?为每个 0 传递0 0 =? will not update the column whereas passing 1 will update it to the value you specified.不会更新列,而传递1会将其更新为您指定的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM