You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS TypeORM(PostgreSQL)批量更新多记录:累加金额并更新日期

问题描述

我有一个实体包含以下字段:

@Column({ name: "total_amount_paid", type: "decimal", precision: 10, scale: 2, nullable: true })
totalAmountPaid: number;

@Column({ name: "last_paid_date", type: "date", nullable: true })
lastPaidDate: Date;

我正在使用基于事务的查询,使用EntityManager的代码如下:

async _updateAgreementsForPayment(
    queryRunnerManager: EntityManager, agreements: AgreementDto[], paidDate: Date
  ): Promise<UpdateResult> {
    const agreementIds = agreements.map((agreement) => agreement.id);
    // Save the updated entities
    return queryRunnerManager.update(
      AgreementEntity, // Target entity
      agreementIds, // Conditions
      { lastPaidDate: paidDate } // Values to be updated
    );
  }

现在我希望在更新lastPaidDate的同时,按照totalAmountPaid = totalAmountPaid + agreementDto.paidAmount的规则更新totalAmountPaid字段,请问是否可以通过批量更新实现?

解决方案

可以实现,需根据不同场景选择对应方式:

场景1:所有协议的paidAmount值相同

如果要更新的所有协议的paidAmount是同一个固定值,直接用EntityManager.update结合SQL表达式即可完成批量更新:

return queryRunnerManager.update(
  AgreementEntity,
  agreementIds,
  {
    lastPaidDate: paidDate,
    totalAmountPaid: () => "total_amount_paid + :paidAmount",
  },
  { parameters: { paidAmount: 固定金额 } }
);

这种方式会生成单条批量更新SQL,执行效率很高。

场景2:每个协议的paidAmount值不同

此时常规批量update无法直接处理(每条记录的增量不同),可以通过QueryBuilder构建CASE WHEN语句实现单条SQL批量更新:

async _updateAgreementsForPayment(
  queryRunnerManager: EntityManager, agreements: AgreementDto[], paidDate: Date
): Promise<UpdateResult> {
  const queryBuilder = queryRunnerManager
    .createQueryBuilder()
    .update(AgreementEntity)
    .set({ lastPaidDate: paidDate })
    .set("total_amount_paid", () => {
      let caseStmt = "CASE";
      agreements.forEach(agreement => {
        caseStmt += ` WHEN id = ${agreement.id} THEN total_amount_paid + ${agreement.paidAmount}`;
      });
      caseStmt += " ELSE total_amount_paid END";
      return caseStmt;
    })
    .where("id IN (:...ids)", { ids: agreements.map(a => a.id) });

  return queryBuilder.execute();
}

该方式会生成一条包含CASE WHEN逻辑的UPDATE语句,一次性完成所有记录的更新,避免多次数据库请求。

如果数据量极小,也可以循环调用update逐个更新,但这种方式会产生多条SQL,性能远不如单条CASE WHEN方案。

内容的提问来源于stack exchange,提问作者Code Guru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 16:24:55