【问题标题】:How to UPDATE multiple rows, based on multiple conditions?如何根据多个条件更新多行?
【发布时间】:2019-10-21 15:01:53
【问题描述】:

我正在尝试为多行更新表中的单个列,但根据其他两列的唯一 where 条件,每行将具有不同的更新日期值。我正在从 csv 读取数据,并简单地更新位于其他两列中的值组合的行中的日期列。

我看过这个

SQL update multiple rows based on multiple where conditions

但 SET 值不会是静态的,并且需要匹配其他两列值为 true 的每一行。这是因为在我的表中,其他两列的组合始终是唯一的。

伪代码

UPDATE mytable SET date = (many different date values)
WHERE col_1 = x and col_2 = y

col_1 和 col_2 值将随 csv 中的每一行而改变,因为这两个值的组合是唯一的。我正在研究在 postgres 中使用 CASE,但我知道它不能用于多个列。

所以基本上,一个 csv 行有一个日期值,必须在 col_1 和 col_2 等于它们各自在 csv 行中的值的记录中更新。如果数据库中不存在这些值,它们将被忽略。

有没有一种优雅的方法可以在单个查询中执行此操作?这个查询是 spring 批处理作业的一部分,所以我可能无法使用本机 postgres 语法,但我什至很难理解查询的格式,所以我以后可以担心语法。我需要多个更新语句吗?如果是这样,我如何在春季批处理作业的写入步骤中实现这一点?

编辑:添加一些示例数据来解释过程

CSV 行:

date,        col_1,    col_2
2021-12-30,  'abc',    'def'
2021-05-30,  'abc',    'zzz'
2021-07-30,  'hfg',    'xxx'

我需要通过查询找到 col_1='abc' AND col_2=def 的记录,然后将日期列更改为 2021-12-30。我需要对每一行都这样做,但我不知道如何格式化 UPDATE 查询。

【问题讨论】:

  • 请提供示例数据和预期结果以澄清您的问题。
  • 好的,这里可能是三个示例 csv 行,将编辑问题进行解释
  • 现在怎么样了? @GMB
  • 如果这是您的示例数据,那么预期结果在哪里?另外,您提到了一些 CSV 数据:数据是存储在 CSV 文件中还是存储在数据库表中?

标签: spring postgresql spring-batch


【解决方案1】:

您可以将 CSV 数据插入(临时)表(例如 mycsv)并使用 UPDATEFROM 子句。例如:

CREATE TEMP TABLE mycsv (date DATE, col_1 TEXT, col_2 TEXT);
COPY mycsv FROM '/path/to/csv/csv-file.csv' WITH (FORMAT csv);
UPDATE mytable m SET date = c.date 
FROM mycsv c WHERE m.col_1 = c.col_1 AND m.col_2 = c.col_2;

【讨论】:

  • 谢谢,我最终使用了类似的东西,但不完全像这里的第二个答案stackoverflow.com/questions/7019831/… 我创建了一个临时数据表,并使用 unnest 映射所有 csv 值,这是一个 java.sql .Array.
【解决方案2】:

创建一个 Itemwriter 实现,并覆盖 write() 方法。该方法接受一个对象列表,每个对象都从您的 ItemProcessor 实现返回。

在 write 方法中,简单地循环遍历对象,然后依次对每个对象调用 update。

例如:

在ItemWriter中:

 @Autowired
 private SomeDao dataAccessObject;

 @Override
 public void write(List<? extends YourDTO> someDTOs) throws Exception {

   for(YourDTO dto: someDTOs) {
      dataAccessObject.update(dto);
   }
 }

在你的 DAO 中:

private static final String sql = "UPDATE mytable SET dateField = ? WHERE col_1 = ? and col_2 = ?";

public void update(YourDTO dto) {

   Object[] parameters = { dto.getDate(), dto.getCol1(), dto.getCol2()};
   int[] types = {Types.DATE, Types.STRING, Types.STRING}; 

   jdbcTemplate.update(sql, parameters, types); 
}

【讨论】:

  • 好吧,我使用的是单独的小任务而不是读取器和写入器,所以我只需将所有内容放在 execute() 方法中即可构建和执行查询。
  • 另外,此更新仅适用于单行不?
  • > 好吧,我使用的是单独的小任务,而不是读取器和写入器,所以我只需将所有内容放在 execute() 方法中即可构建和执行查询。请发布您的代码,以便我们进一步提供帮助。 > 此外,此更新仅适用于单行,不是吗?否 - 对于传递给编写器的每个项目,更新将发生一次
  • 我试图避免批量更新,出于性能原因,我只向数据库发送一个大型更新查询。
  • > 我试图避免批量更新,这就是 Spring Batch 的重点
猜你喜欢
  • 2021-12-03
  • 2018-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多