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

如何用Prisma在单查询中更新多条不同值的记录

Prisma批量更新多条不同值记录的解决方案

我需要使用Prisma批量更新多条记录,但updateMany只能为符合条件的所有记录设置同一个字段值,无法实现类似SQL中多条UPDATE table SET field = "值N" WHERE id = N的效果。之前尝试的代码无法正常工作:

async updateProductsQuantity(
    data: IUpdateProductsQuantityDTO
): Promise<void> {
    await prisma.product.updateMany({
        where: {
            id: {
                in: data.ids
            }
        },
        data: {
            currentQuantity: data.quantities
        }
    });
}

方法一:事务+单个Update循环

利用Prisma的事务机制,将多个单个update操作包裹在事务中,保证原子性。这种方式代码简洁、类型安全,适合数据量不大的场景。

async updateProductsQuantity(data: IUpdateProductsQuantityDTO): Promise<void> {
    // 校验输入合法性,避免长度不匹配导致错误
    if (data.ids.length !== data.quantities.length) {
        throw new Error('ids与quantities数组长度必须一致');
    }

    // 批量生成update操作,通过事务执行
    await prisma.$transaction(
        data.ids.map((id, index) => 
            prisma.product.update({
                where: { id },
                data: { currentQuantity: data.quantities[index] }
            })
        )
    );
}

方法二:原生SQL动态生成CASE语句

通过原生SQL的CASE语法,一次查询完成批量更新,性能更优,适合数据量大的场景。注意要处理SQL注入风险,优先使用参数化查询。

安全的参数化版本(推荐)

async updateProductsQuantity(data: IUpdateProductsQuantityDTO): Promise<void> {
    if (data.ids.length !== data.quantities.length) {
        throw new Error('ids与quantities数组长度必须一致');
    }

    const params: (number | string)[] = [];
    const caseClauses: string[] = [];
    const inPlaceholders: string[] = [];

    // 构建参数和SQL片段
    data.ids.forEach((id, index) => {
        params.push(id, data.quantities[index]);
        // 占位符使用$N格式(适配PostgreSQL,MySQL用?)
        caseClauses.push(`WHEN id = $${params.length - 1} THEN $${params.length}`);
        inPlaceholders.push(`$${params.length - 1}`);
    });

    const query = `
        UPDATE product 
        SET currentQuantity = CASE ${caseClauses.join(' ')} END 
        WHERE id IN (${inPlaceholders.join(', ')})
    `;

    await prisma.$executeRaw(query, ...params);
}

注意事项

  • 如果使用MySQL,占位符要换成?,调整对应的参数索引逻辑。
  • 务必使用参数化查询,避免直接拼接用户输入导致SQL注入。

两种方案对比

  • 事务循环:优点是代码易维护、Prisma类型校验完整;缺点是数据量过大时会生成多个SQL查询,性能略有下降。
  • 原生CASE更新:优点是单查询完成,性能高效;缺点需要手动处理SQL语法和参数化,失去Prisma的类型安全特性。

内容的提问来源于stack exchange,提问作者Caio Pereira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 20:50:35